/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/KeeperProxy.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
5 | | import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
6 | | import "./libraries/StructData.sol";
7 | |
8 | | interface IPerpetualVault {
9 | | function market() external view returns (address);
10 | | function gmxUtils() external view returns (address);
11 | | function run(bool, bool, uint256, MarketPrices memory, bytes[] memory) external;
12 | | function runNextAction(MarketPrices memory, bytes[] memory) external;
13 | | function cancelDeposit() external;
14 | | function cancelOrder() external;
15 | | function claimCollateralRebates(uint256[] memory) external;
16 | | }
17 | |
18 | | interface IGmxUtils {
19 | | function getMarket(address market) external view returns (MarketProps memory);
20 | | }
21 | |
22 | | interface AggregatorV2V3Interface {
23 | | function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);
24 | | }
25 | |
26 | | interface IERC20 {
27 | | function decimals() external view returns (uint8);
28 | | }
29 | |
30 | | /**
31 | | * @title KeeperProxy
32 | | * @dev This contract acts as a proxy for executing keeper functions on a PerpetualVault.
33 | | * It handles price validation and ensures the correct execution of actions.
34 | | */
35 | | contract KeeperProxy is Initializable, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
36 | |
37 | | uint256 constant BPS = 10_000;
38 | | uint256 private constant GRACE_PERIOD_TIME = 3600;
39 | | AggregatorV2V3Interface internal sequencerUptimeFeed;
40 | | mapping (address => address) public dataFeed;
41 | | uint256 public threshold;
42 | | uint256 maxTimeWindow;
43 | |
44 | | /**
45 | | * @notice Initializes the contract.
46 | | * @dev Sets the initial threshold value and initializes inherited contracts.
47 | | */
48 | | function initialize() external initializer {
49 | | __Ownable2Step_init();
50 | | sequencerUptimeFeed = AggregatorV2V3Interface(0xFdB631F5EE196F0ed6FAa767959853A9F217697D);
51 | | threshold = 100;
52 | | maxTimeWindow = 30;
53 | | }
54 | |
55 | | /**
56 | | * @notice Executes a run action on the specified PerpetualVault.
57 | | * @dev Validates the price before executing the run action.
58 | | * @param perpVault The address of the PerpetualVault.
59 | | * @param isOpen Indicates if the position should be opened.
60 | | * @param isLong Indicates if the position is long.
61 | | * @param _leverage The leverage value for the position.
62 | | * @param prices The market prices used for validation.
63 | | * @param _swapData The swap data for the run action.
64 | | */
65 | | function run(
66 | | address perpVault,
67 | | bool isOpen,
68 | | bool isLong,
69 | | uint256 _leverage,
70 | | MarketPrices memory prices,
71 | | bytes[] memory _swapData
72 | | ) external onlyOwner {
73 | | _validatePrice(perpVault, prices);
74 | | IPerpetualVault(perpVault).run(isOpen, isLong, _leverage, prices, _swapData);
75 | | }
76 | |
77 | | /**
78 | | * @notice Executes the next action on the specified PerpetualVault.
79 | | * @dev Validates the price before executing the next action.
80 | | * @param perpVault The address of the PerpetualVault.
81 | | * @param prices The market prices used for validation.
82 | | * @param _swapData The swap data for the next action.
83 | | */
84 | | function runNextAction(address perpVault, MarketPrices memory prices, bytes[] memory _swapData) external onlyOwner {
85 | | _validatePrice(perpVault, prices);
86 | | IPerpetualVault(perpVault).runNextAction(prices, _swapData);
87 | | }
88 | |
89 | | /**
90 | | * @notice Call `cancelDeposit` function of a vault
91 | | * @param perpVault The address of the PerpetualVault
92 | | */
93 | | function cancelDeposit(address perpVault) external onlyOwner {
94 | | IPerpetualVault(perpVault).cancelDeposit();
95 | | }
96 | |
97 | | /**
98 | | * @notice
99 | | * GMX keepers would not always execute orders in a reasonable amount of time.
100 | | * This function is called when the requested Order is not executed in GMX side.
101 | | */
102 | | function cancelOrder(address perpVault) external onlyOwner {
103 | | IPerpetualVault(perpVault).cancelOrder();
104 | | }
105 | |
106 | | function claimCollateralRebates(address perpVault, uint256[] memory timeKeys) external onlyOwner {
107 | | IPerpetualVault(perpVault).claimCollateralRebates(timeKeys);
108 | | }
109 | |
110 | | /**
111 | | * @notice Sets the data feed address for a specific token.
112 | | * @dev Can only be called by the owner of the contract.
113 | | * @param token The address of the token.
114 | | * @param feed The address of the data feed.
115 | | */
116 | | function setDataFeed(address token, address feed) external onlyOwner {
117 | | require(token != address(0), "zero address");
118 | | require(feed != address(0), "zero address");
119 | | dataFeed[token] = feed;
120 | | }
121 | |
122 | | /**
123 | | * @notice Sets the threshold value for price validation.
124 | | * @dev Can only be called by the owner of the contract.
125 | | * @param _threshold The new threshold value.
126 | | */
127 | | function setThreshold(uint256 _threshold) external onlyOwner {
128 | | require(_threshold > 0, "zero value");
129 | | threshold = _threshold;
130 | | }
131 | |
132 | | function setMaxTimeWindow(uint256 _maxTimeWindow) external onlyOwner {
133 | | require(_maxTimeWindow > 0, "zero value");
134 | | maxTimeWindow = _maxTimeWindow;
135 | | }
136 | |
137 | | /**
138 | | * @notice Validates the market prices against the Chainlink data feed.
139 | | * @dev Internal function to check the prices of the market tokens.
140 | | * @param perpVault The address of the PerpetualVault.
141 | | * @param prices The market prices used for validation.
142 | | */
143 | | function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
144 | | // L2 Sequencer check
145 | | (
146 | | /*uint80 roundID*/,
147 | | int256 answer,
148 | | uint256 startedAt,
149 | | /*uint256 updatedAt*/,
150 | | /*uint80 answeredInRound*/
151 | | ) = AggregatorV2V3Interface(sequencerUptimeFeed).latestRoundData();
152 | | bool isSequencerUp = answer == 0;
153 | | require(isSequencerUp, "sequencer is down");
154 | | // Make sure the grace period has passed after the sequencer is back up.
155 | | uint256 timeSinceUp = block.timestamp - startedAt;
156 | | require(timeSinceUp > GRACE_PERIOD_TIME, "Grace period is not over");
157 | |
158 | | address market = IPerpetualVault(perpVault).market();
159 | | address gmxUtils = IPerpetualVault(perpVault).gmxUtils();
160 | | MarketProps memory marketData = IGmxUtils(gmxUtils).getMarket(market);
161 | |
162 | | _check(marketData.indexToken, prices.indexTokenPrice.min);
163 | | _check(marketData.indexToken, prices.indexTokenPrice.max);
164 | | _check(marketData.longToken, prices.indexTokenPrice.min);
165 | | _check(marketData.longToken, prices.indexTokenPrice.max);
166 | | _check(marketData.shortToken, prices.shortTokenPrice.min);
167 | | _check(marketData.shortToken, prices.shortTokenPrice.max);
168 | | }
169 | |
170 | | /**
171 | | * @notice Checks the price difference between the given price and the Chainlink price.
172 | | * @dev Internal function to ensure the price difference is within the threshold.
173 | | * @param token The address of the token.
174 | | * @param price The price to be checked.
175 | | */
176 | | function _check(address token, uint256 price) internal view {
177 | | // https://github.com/code-423n4/2021-06-tracer-findings/issues/145
178 | | (, int chainLinkPrice, , uint256 updatedAt, ) = AggregatorV2V3Interface(dataFeed[token]).latestRoundData();
179 | | require(updatedAt > block.timestamp - maxTimeWindow, "stale price feed");
180 | | uint256 decimals = 30 - IERC20(token).decimals();
181 | | price = price / 10 ** (decimals - 8); // Chainlink price decimals is always 8.
182 | | require(_absDiff(price, uint256(chainLinkPrice)) * BPS / uint256(chainLinkPrice) < threshold, "price offset too big");
183 | | }
184 | |
185 | | /**
186 | | * @notice Calculates the absolute difference between two numbers.
187 | | * @dev Internal pure function to calculate the absolute difference.
188 | | * @param a The first number.
189 | | * @param b The second number.
190 | | * @return diff The absolute difference between the two numbers.
191 | | */
192 | | function _absDiff(uint256 a, uint256 b) internal pure returns (uint256 diff) {
193 | | if (a > b) return a - b;
194 | | else return b - a;
195 | | }
196 | | }
197 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/MockParaswapUtils.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6 | | import {console} from "forge-std/Test.sol";
7 | | interface IAugustusSwapper {
8 | | function getTokenTransferProxy() external view returns (address);
9 | | }
10 | |
11 | | contract MockParaSwapUtils {
12 | | using SafeERC20 for IERC20;
13 | |
14 | | address PARASWAP_ROUTER;
15 | | bool routerSet;
16 | |
17 | | function setRouter(address _paraswapRouter) public {
18 | | require(!routerSet);
19 | | PARASWAP_ROUTER = _paraswapRouter;
20 | | routerSet = true;
21 | | }
22 | |
23 | * | function swap(address to, bytes memory callData) public {
24 | * | _validateCallData(to, callData);
25 | * | address approvalAddress = IAugustusSwapper(to).getTokenTransferProxy();
26 | * | address fromToken;
27 | * | uint256 fromAmount;
28 | | assembly {
29 | * | fromToken := mload(add(callData, 36)) //@audit replaced 68th byte by fuzzer
30 | * | fromAmount := mload(add(callData, 100))
31 | | }
32 | * | IERC20(fromToken).safeApprove(approvalAddress, fromAmount);
33 | * | (bool success, ) = to.call(callData);
34 | * | require(success, "paraswap call reverted");
35 | | }
36 | |
37 | * | function _validateCallData(
38 | | address to,
39 | | bytes memory callData
40 | * | ) internal view {
41 | * | assert(PARASWAP_ROUTER != address(0));
42 | * | require(to == PARASWAP_ROUTER, "invalid paraswap callee");
43 | |
44 | * | address receiver;
45 | | assembly {
46 | * | receiver := mload(add(callData, 196))
47 | | }
48 | * | require(receiver == address(this), "invalid paraswap calldata");
49 | | }
50 | | }
51 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/PerpetualVault.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | | pragma abicoder v2;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
8 | | import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
9 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
10 | | import "./libraries/Order.sol";
11 | | import "./libraries/ParaSwapUtils.sol";
12 | | import "./interfaces/gmx/IDataStore.sol";
13 | | import "./interfaces/gmx/IReader.sol";
14 | | import "./interfaces/gmx/IExchangeRouter.sol";
15 | | import "./interfaces/IGmxUtils.sol";
16 | | import {Test, console} from "forge-std/Test.sol";
17 | |
18 | | /**
19 | | * @notice
20 | | * a vault contract that trades on GMX market and Paraswap DEX Aggregator
21 | | * it gets the signal(long/short/close flag and leverage value) from the off-chain script.
22 | | * if signal is long and leverage is 1x, swap collateral to `indexToken`。
23 | | * if signal is long with leverage above 1x, open a long position with a specified leverage on gmx market.
24 | | * if signal is short, open a short position with a specified leverage on gmx market.
25 | | *
26 | | * For now, we only support the GMX market in which `indexToken` is the same as `longToken`.
27 | | * We think the price impact of deposit and withdraw as a swap slippage loss. As if the more swap amount in dex, the much loss we get.
28 | | * GMX charges negative fee against collateral so collateral amount is decreased over time. It makes leverage value increasing.
29 | | * We have offchain script to address this. The offchain script monitors leverage value and adjusts when it exceeds the risky value to avoid liquidation.
30 | | */
31 | | contract PerpetualVault is
32 | | Initializable,
33 | | Ownable2StepUpgradeable,
34 | | ReentrancyGuardUpgradeable
35 | | {
36 | | using SafeERC20 for IERC20;
37 | |
38 | | struct SwapProgress {
39 | | // swap process involves asynchronous operation so store swap progress data
40 | | bool isCollateralToIndex; // if swap `collateralToken` to `indexToken`, true and vice versa.
41 | | uint256 swapped; // the amount of output token that has already been swapped.
42 | | uint256 remaining; // the amount of input token that remains to be swapped
43 | | }
44 | |
45 | | enum NextActionSelector {
46 | | NO_ACTION, // state where no action is required
47 | | INCREASE_ACTION, // represents increasing actions such as increasing a GMX perps position or increasing a spot position
48 | | SWAP_ACTION, // represents swapping a token, either collateral to index or vice versa
49 | | WITHDRAW_ACTION, // represents withdrawing funds
50 | | COMPOUND_ACTION, // whenver claiming positive funding fee, we could have idle funds in the vault.
51 | | // If it's enough to deposit more into GMX, triggers `COMPOUND_ACTION`.
52 | | SETTLE_ACTION, // settle fees and ensure state is up-to-date prior to withdrawals
53 | | FINALIZE
54 | | }
55 | |
56 | | enum FLOW {
57 | | NONE,
58 | | DEPOSIT,
59 | | SIGNAL_CHANGE,
60 | | WITHDRAW,
61 | | COMPOUND
62 | | }
63 | |
64 | | struct Action {
65 | | NextActionSelector selector;
66 | | bytes data;
67 | | }
68 | |
69 | | struct DepositInfo {
70 | | uint256 amount; // amount of deposit
71 | | uint256 shares; // amount of share corresponding to deposit amount
72 | | address owner; // depositor address
73 | | uint256 executionFee; // execution fee
74 | | uint256 timestamp; // timestamp of deposit
75 | | address recipient; // address of recipient when withdrawing, which is set at the moment of withdrawal request
76 | | }
77 | |
78 | | string public name;
79 | |
80 | | // Vault variables
81 | | uint256 public constant PRECISION = 1e30;
82 | * | uint256 public constant BASIS_POINTS_DIVISOR = 10_000;
83 | |
84 | * | uint256 public totalShares;
85 | * | uint256 public counter;
86 | * | mapping(uint256 => DepositInfo) public depositInfo;
87 | | mapping(address => EnumerableSet.UintSet) userDeposits;
88 | |
89 | | address public market;
90 | * | address public indexToken;
91 | * | IERC20 public collateralToken;
92 | | IGmxUtils public gmxUtils;
93 | |
94 | | address public keeper;
95 | * | address public treasury;
96 | * | bytes32 public curPositionKey; // current open positionKey
97 | * | uint256 public maxDepositAmount; // max cap of collateral token that can be managrable in vault
98 | * | uint256 public minDepositAmount; // min deposit amount of collateral
99 | * | uint256 public totalDepositAmount; // current total collateral token amount in the vault
100 | | uint256 public minEth; // minimum eth amount to run signal change action
101 | | uint256 public governanceFee; // percentage of fee to charge
102 | | uint256 public callbackGasLimit; // gas amount to compensate keeper calls and GMX callback function
103 | * | uint256 public lockTime; // `lockTime` prevents the immediate withdrawal attempts after deposit
104 | | uint256 public leverage; // GMX position leverage value (decimals is 10000)
105 | |
106 | * | Action public nextAction;
107 | * | FLOW public flow;
108 | | bytes flowData;
109 | * | bool public beenLong; // true if current open position is long
110 | * | bool public positionIsClosed; // true if there's no open position
111 | | bool _gmxLock; // this is true while gmx action is in progress. i.e. from gmx call to gmx callback
112 | |
113 | * | SwapProgress public swapProgressData; // in order to deal with gmx swap failures, we utilize this struct to keep track of what has already been swapped to avoid overswapping
114 | | MarketPrices marketPrices;
115 | | bool public depositPaused; // if true, deposit is paused
116 | |
117 | | event Minted(
118 | | uint256 depositId,
119 | | address depositor,
120 | | uint256 shareAmount,
121 | | uint256 depositAmount
122 | | );
123 | | event Burned(
124 | | uint256 depositId,
125 | | address recipient,
126 | | uint256 shareAmount,
127 | | uint256 amount
128 | | );
129 | | event DexSwap(
130 | | address inputToken,
131 | | uint256 inputAmount,
132 | | address outputToken,
133 | | uint256 outputAmount
134 | | );
135 | | event GmxSwap(
136 | | address inputToken,
137 | | uint256 inputAmount,
138 | | address outputToken,
139 | | uint256 outputAmount
140 | | );
141 | | event Settled(uint256 positiveFundingFeeAmount, uint256 negativeFeeAmount);
142 | | event FeeCollected(address token, uint256 amount);
143 | | event GmxPositionCallbackCalled(bytes32 requestKey, bool success);
144 | | event SignalChanged(bool isOpen, bool isLong, uint256 leverage);
145 | | event TokenTranferFailed(address recipient, uint256 amount);
146 | |
147 | | modifier onlyKeeper() {
148 | * | require(msg.sender == keeper, "!keeper");
149 | | _;
150 | | }
151 | |
152 | | // Lock the contract from the moment we create position to the moment we get the callback from GMX keeper
153 | | modifier gmxLock() {
154 | * | require(_gmxLock == false, "gmx action lock");
155 | | _;
156 | | }
157 | |
158 | | // we prevent user interactions while a flow is still being in progress.
159 | | modifier noneFlow() {
160 | * | require(flow == FLOW.NONE, "flow in progress");
161 | | _;
162 | | }
163 | |
164 | | /**
165 | | * @notice
166 | | * `collateralToken` can be ETH, WETH, BTC, LINK, UNI, USDC, USDT, DAI, FRAX.
167 | | * @param _name Perpetual Vault indentifier
168 | | * @param _market address of GMX market
169 | | * @param _keeper keeper address
170 | | * @param _treasury fee receiver
171 | | * @param _gmxUtils address of GMXUtils contract
172 | | * @param _minDepositAmount minimum deposit amount
173 | | * @param _maxDepositAmount maximum deposit amount
174 | | */
175 | | function initialize(
176 | | string memory _name,
177 | | address _market,
178 | | address _keeper,
179 | | address _treasury,
180 | | address _gmxUtils,
181 | | uint256 _minDepositAmount,
182 | | uint256 _maxDepositAmount
183 | | ) external initializer {
184 | | __Ownable2Step_init();
185 | | __ReentrancyGuard_init();
186 | | name = _name;
187 | | require(_market != address(0), "zero address");
188 | | require(_gmxUtils != address(0), "zero address");
189 | | market = _market;
190 | | IGmxUtils(_gmxUtils).setPerpVault(address(this));
191 | | gmxUtils = IGmxUtils(_gmxUtils);
192 | | MarketProps memory marketInfo = IGmxUtils(_gmxUtils).getMarket(market);
193 | | indexToken = marketInfo.indexToken;
194 | | collateralToken = IERC20(marketInfo.shortToken);
195 | | require(_keeper != address(0), "zero address");
196 | | require(_treasury != address(0), "zero address");
197 | | keeper = _keeper;
198 | | treasury = _treasury;
199 | | governanceFee = 500; // 5%
200 | | minDepositAmount = _minDepositAmount;
201 | | maxDepositAmount = _maxDepositAmount;
202 | | minEth = 0.002 ether;
203 | | callbackGasLimit = 2_000_000;
204 | | positionIsClosed = true;
205 | | lockTime = 7 * 24 * 3600; // 1 week
206 | | }
207 | |
208 | | /**
209 | | * @notice Deposits collateral tokens into the vault.
210 | | * @dev This function checks if deposits are paused, validates the deposit amount,
211 | | * and transfers the collateral tokens from the sender to the contract.
212 | | * If the position is closed, it directly mints shares for the deposit amount.
213 | | * If the position is open, it sets up the next action to register the requested position params.
214 | | * @param amount The amount of collateral tokens to deposit.
215 | | */
216 | | function deposit(
217 | | uint256 amount
218 | | ) external payable virtual nonReentrant noneFlow {
219 | | //NOTE: changed by fuzzer
220 | | require(depositPaused == false, "paused");
221 | | flow = FLOW.DEPOSIT;
222 | | // flowData = abi.encode(msg.sender);
223 | | require(amount >= minDepositAmount, "insufficient amount");
224 | | require(
225 | | totalDepositAmount + amount <= maxDepositAmount,
226 | | "exceeds max deposit cap"
227 | | );
228 | | collateralToken.safeTransferFrom(msg.sender, address(this), amount);
229 | | counter++;
230 | | depositInfo[counter] = DepositInfo(
231 | | amount,
232 | | 0,
233 | | msg.sender,
234 | | 0,
235 | | block.timestamp,
236 | | address(0)
237 | | );
238 | | totalDepositAmount += amount;
239 | | EnumerableSet.add(userDeposits[msg.sender], counter);
240 | |
241 | | if (positionIsClosed) {
242 | | _mint(counter, amount, false);
243 | | _finalize(hex"");
244 | | } else {
245 | | _payExecutionFee(counter);
246 | | // mint share token in the NextAction to involve off-chain price data and improve security
247 | | nextAction.selector = NextActionSelector.INCREASE_ACTION;
248 | | nextAction.data = abi.encode(beenLong, leverage);
249 | | }
250 | | }
251 | |
252 | | /**
253 | | * @notice Withdraws collateral of user.
254 | | * @dev If position is GMX position, first call `settle` function to settle pending fees
255 | | * in order to avoid charging all fees from the withdrawer.
256 | | * @param recipient The address to receive the tokens.
257 | | * @param depositId The deposit ID to withdraw.
258 | | */
259 | | function withdraw(
260 | | address recipient,
261 | | uint256 depositId
262 | | ) public payable virtual nonReentrant noneFlow {
263 | | //NOTE: changed by fuzzer
264 | | flow = FLOW.WITHDRAW;
265 | | flowData = abi.encode(depositId, msg.sender);
266 | |
267 | | require(recipient != address(0), "zero address");
268 | | require(
269 | | depositInfo[depositId].timestamp + lockTime < block.timestamp,
270 | | "locked"
271 | | );
272 | | require(
273 | | EnumerableSet.contains(userDeposits[msg.sender], depositId),
274 | | "not a valid user"
275 | | );
276 | | require(depositInfo[depositId].shares > 0, "zero share value");
277 | |
278 | | depositInfo[depositId].recipient = recipient;
279 | | if (curPositionKey != bytes32(0)) {
280 | | _payExecutionFee(depositId);
281 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
282 | | _settle(); // Settles any outstanding fees and updates state before processing withdrawal
283 | | } else {
284 | | _withdraw(depositId, hex"00");
285 | | }
286 | | }
287 | |
288 | | /**
289 | | * @notice Off-chain script calls `run` function to change position type (long/short/close).
290 | | * @param isOpen If true, open a position; if false, close the current position.
291 | | * @param isLong If true, open a long position; if false, open a short position.
292 | | * @param _leverage Leverage value in GMX protocol.
293 | | * @param prices GMX price data of market tokens from GMX API call.
294 | | * @param metadata Swap transaction data generated by off-chain script.
295 | | */
296 | | function run(
297 | | bool isOpen,
298 | | bool isLong,
299 | | uint256 _leverage,
300 | | MarketPrices memory prices,
301 | | bytes[] memory metadata
302 | | ) external virtual nonReentrant noneFlow onlyKeeper {
303 | |
304 | | //NOTE: visibility changed by fuzzer
305 | | require(
306 | | address(gmxUtils).balance > minEth,
307 | | "lower than minimum eth balance"
308 | | );
309 | | flow = FLOW.SIGNAL_CHANGE;
310 | | flowData = abi.encode(_leverage, msg.sender);
311 | | marketPrices = prices;
312 | |
313 | | if (isOpen) {
314 | | if (positionIsClosed) {
315 | | require(_isFundIdle(), "insufficient balance to open position");
316 | | if (_isLongOneLeverage(isLong, _leverage)) {
317 | | _runSwap(metadata, true);
318 | | } else {
319 | | uint256 acceptablePrice = abi.decode(
320 | | metadata[0],
321 | | (uint256)
322 | | );
323 | | _createIncreasePosition(isLong, _leverage, acceptablePrice);
324 | | }
325 | | } else {
326 | | if (beenLong == isLong) {
327 | | revert("no action needed");
328 | | } else {
329 | | // Close current position first and then open the requested position in the next action
330 | | nextAction.selector = NextActionSelector.INCREASE_ACTION;
331 | | nextAction.data = abi.encode(isLong, _leverage);
332 | | if (_isLongOneLeverage(beenLong, leverage)) {
333 | | _runSwap(metadata, false);
334 | | } else {
335 | | uint256 acceptablePrice = abi.decode(
336 | | metadata[0],
337 | | (uint256)
338 | | );
339 | | _createDecreasePosition(
340 | | 0,
341 | | 0,
342 | | beenLong,
343 | | acceptablePrice
344 | | );
345 | | }
346 | | }
347 | | }
348 | | } else {
349 | | if (positionIsClosed == false) {
350 | | if (_isLongOneLeverage(beenLong, leverage)) {
351 | | _runSwap(metadata, false);
352 | | } else {
353 | | uint256 acceptablePrice = abi.decode(
354 | | metadata[0],
355 | | (uint256)
356 | | );
357 | | _createDecreasePosition(0, 0, beenLong, acceptablePrice);
358 | | }
359 | | } else {
360 | | revert("no action needed");
361 | | }
362 | | }
363 | | }
364 | |
365 | | /**
366 | | * @notice `flow` is not completed in one tx. So in that case, set up the next action data
367 | | * and run the `nextAction`.
368 | | * @param prices GMX price data of market tokens from GMX API call
369 | | * @param metadata swap tx data. generated by off-chain script
370 | | */
371 | | function runNextAction(
372 | | MarketPrices memory prices,
373 | | bytes[] memory metadata
374 | | ) external virtual nonReentrant gmxLock onlyKeeper {
375 | | //NOTE: changed by fuzzer
376 | | marketPrices = prices;
377 | | Action memory _nextAction = nextAction;
378 | | delete nextAction;
379 | | if (_nextAction.selector == NextActionSelector.INCREASE_ACTION) {
380 | | (bool _isLong, uint256 _leverage) = abi.decode(
381 | | _nextAction.data,
382 | | (bool, uint256)
383 | | );
384 | |
385 | | if (_isLongOneLeverage(_isLong, _leverage)) {
386 | | _runSwap(metadata, true);
387 | | } else {
388 | | // swap indexToken that could be generated from the last action into collateralToken
389 | | // use only DexSwap
390 | | if (metadata[1].length > 0) {
391 | | (PROTOCOL _protocol, bytes memory data) = abi.decode(
392 | | metadata[0],
393 | | (PROTOCOL, bytes)
394 | | );
395 | | require(_protocol == PROTOCOL.DEX, "invalid metadata");
396 | | _doDexSwap(data, false);
397 | | }
398 | | uint256 acceptablePrice = abi.decode(metadata[0], (uint256));
399 | | _createIncreasePosition(_isLong, _leverage, acceptablePrice);
400 | | }
401 | | } else if (_nextAction.selector == NextActionSelector.WITHDRAW_ACTION) {
402 | | // swap indexToken that could be generated from settle action into collateralToken
403 | | // use only DexSwap
404 | | if (metadata[1].length > 0) {
405 | | (PROTOCOL _protocol, bytes memory data) = abi.decode(
406 | | metadata[0],
407 | | (PROTOCOL, bytes)
408 | | );
409 | | require(_protocol == PROTOCOL.DEX, "invalid metadata");
410 | | _doDexSwap(data, false);
411 | | }
412 | | (uint256 depositId, ) = abi.decode(flowData, (uint256, address));
413 | |
414 | | _withdraw(depositId, metadata[0]);
415 | | } else if (_nextAction.selector == NextActionSelector.SWAP_ACTION) {
416 | | (, bool isCollateralToIndex) = abi.decode(
417 | | _nextAction.data,
418 | | (uint256, bool)
419 | | );
420 | | _runSwap(metadata, isCollateralToIndex);
421 | | } else if (_nextAction.selector == NextActionSelector.SETTLE_ACTION) {
422 | | _settle();
423 | | } else if (_nextAction.selector == NextActionSelector.FINALIZE) {
424 | | if (metadata.length > 0) {
425 | | _runSwap(metadata, false);
426 | | }
427 | | _finalize(_nextAction.data);
428 | | } else if (positionIsClosed == false && _isFundIdle()) {
429 | | flow = FLOW.COMPOUND;
430 | | if (_isLongOneLeverage(beenLong, leverage)) {
431 | | _runSwap(metadata, true);
432 | | } else {
433 | | uint256 acceptablePrice = abi.decode(metadata[0], (uint256));
434 | | _createIncreasePosition(beenLong, leverage, acceptablePrice);
435 | | }
436 | | }
437 | | }
438 | |
439 | | /**
440 | | * @notice Cancel the ongoing deposit action.
441 | | */
442 | * | function cancelDeposit() external nonReentrant gmxLock onlyKeeper {
443 | * | require(flow == FLOW.DEPOSIT, "invalid");
444 | * | uint256 depositId = counter;
445 | * | collateralToken.safeTransfer(
446 | * | depositInfo[depositId].owner,
447 | * | depositInfo[depositId].amount
448 | | );
449 | * | totalDepositAmount = totalDepositAmount - depositInfo[depositId].amount;
450 | * | EnumerableSet.remove(
451 | * | userDeposits[depositInfo[depositId].owner],
452 | * | depositId
453 | | );
454 | |
455 | | // refund fee
456 | * | uint256 usedFee = callbackGasLimit * tx.gasprice;
457 | * | if (depositInfo[counter].executionFee > usedFee) {
458 | | IGmxUtils(gmxUtils).refundExecutionFee(
459 | | depositInfo[counter].owner,
460 | | depositInfo[counter].executionFee - usedFee
461 | | );
462 | | }
463 | |
464 | * | delete depositInfo[depositId];
465 | * | delete nextAction;
466 | * | delete flowData;
467 | * | flow = FLOW.NONE;
468 | | }
469 | |
470 | | /**
471 | | * @notice Cancel order when order is not executed from GMX side
472 | | * Cancelling order is valid after the expiration time has passed since the order request is registered.
473 | | */
474 | | function cancelOrder() external nonReentrant onlyKeeper {
475 | | require(_gmxLock, "invalid call");
476 | | IGmxUtils(gmxUtils).cancelOrder();
477 | | }
478 | |
479 | | /**
480 | | * @notice
481 | | * GMX cap negative price impact on decrease orders.
482 | | * If a trade is closed with a price impact higher than this percentage,
483 | | * then the additional impact would become claimable after a few days.
484 | | * This function is used to claim this manually.
485 | | * Resolves who and how much via off-chain script
486 | | */
487 | | function claimCollateralRebates(
488 | | uint256[] memory timeKeys
489 | | ) external nonReentrant noneFlow onlyKeeper {
490 | | address[] memory markets = new address[](1);
491 | | markets[0] = market;
492 | | address[] memory tokens = new address[](1);
493 | | tokens[0] = address(collateralToken);
494 | |
495 | | IGmxUtils(gmxUtils).claimCollateralRebates(
496 | | markets,
497 | | tokens,
498 | | timeKeys,
499 | | treasury
500 | | );
501 | | }
502 | |
503 | | /**
504 | | * @notice Callback function that is called when an order on GMX is executed successfully.
505 | | * This function handles the post-execution logic based on the type of order that was executed.
506 | | * @dev This callback function must never be reverted. It should wrap revertible external calls with `try-catch`.
507 | | * @param requestKey The request key of the executed order.
508 | | * @param positionKey The position key.
509 | | * @param orderResultData Data from the order execution.
510 | | */
511 | | function afterOrderExecution(
512 | | bytes32 requestKey,
513 | | bytes32 positionKey,
514 | | IGmxUtils.OrderResultData memory orderResultData
515 | | ) external virtual nonReentrant {
516 | | require(msg.sender == address(gmxUtils), "invalid caller");
517 | | _updateMarketPrice();
518 | |
519 | | _gmxLock = false;
520 | | // If the current action is `settle`
521 | | if (orderResultData.isSettle) {
522 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
523 | | emit GmxPositionCallbackCalled(requestKey, true);
524 | | // emit Settled(positiveFundingFeeAmount, negativeFeeAmount);
525 | | return;
526 | | }
527 | | if (orderResultData.orderType == Order.OrderType.MarketIncrease) {
528 | | curPositionKey = positionKey;
529 | | if (flow == FLOW.DEPOSIT) {
530 | | uint256 curAmount = _totalAmount(marketPrices);
531 | | uint256 prevAmount = abi.decode(flowData, (uint256));
532 | | if (curAmount > prevAmount) {
533 | | uint256 increased = (curAmount - prevAmount) /
534 | | marketPrices.shortTokenPrice.max;
535 | | _mint(counter, increased, false);
536 | | }
537 | | nextAction.selector = NextActionSelector.FINALIZE;
538 | | } else {
539 | | uint256 _leverage;
540 | | if (flowData.length > 0) {
541 | | (_leverage, ) = abi.decode(flowData, (uint256, address));
542 | | } else {
543 | | _leverage = leverage;
544 | | }
545 | | _updateState(false, _leverage, orderResultData.isLong);
546 | | }
547 | | } else if (
548 | | orderResultData.orderType == Order.OrderType.MarketDecrease
549 | | ) {
550 | | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey);
551 | | if (sizeInUsd == 0) {
552 | | curPositionKey = bytes32(0);
553 | | }
554 | | if (flow == FLOW.WITHDRAW) {
555 | | nextAction.selector = NextActionSelector.FINALIZE;
556 | | uint256 prevCollateralBalance = collateralToken.balanceOf(
557 | | address(this)
558 | | ) - orderResultData.outputAmount;
559 | | nextAction.data = abi.encode(
560 | | prevCollateralBalance,
561 | | sizeInUsd == 0,
562 | | false
563 | | );
564 | | // _handleReturn(orderResultData.outputAmount, sizeInUsd == 0, false);
565 | | } else {
566 | | nextAction.selector = NextActionSelector.FINALIZE;
567 | | _updateState(true, 0, false);
568 | | }
569 | | } else if (orderResultData.orderType == Order.OrderType.MarketSwap) {
570 | | uint256 outputAmount = orderResultData.outputAmount;
571 | | if (swapProgressData.isCollateralToIndex) {
572 | | emit GmxSwap(
573 | | address(collateralToken),
574 | | swapProgressData.remaining,
575 | | indexToken,
576 | | outputAmount
577 | | );
578 | | } else {
579 | | emit GmxSwap(
580 | | indexToken,
581 | | swapProgressData.remaining,
582 | | address(collateralToken),
583 | | outputAmount
584 | | );
585 | | }
586 | |
587 | | if (flow == FLOW.DEPOSIT) {
588 | | _mint(counter, outputAmount + swapProgressData.swapped, false);
589 | | _finalize(hex"");
590 | | } else if (flow == FLOW.WITHDRAW) {
591 | | _handleReturn(
592 | | outputAmount + swapProgressData.swapped,
593 | | false,
594 | | false
595 | | );
596 | | } else {
597 | | // Same as if (flow == FLOW.SIGNAL_CHANGE || FLOW.COMPOUND)
598 | | if (orderResultData.outputToken == indexToken) {
599 | | _updateState(false, BASIS_POINTS_DIVISOR, true);
600 | | } else {
601 | | _updateState(true, 0, false);
602 | | }
603 | | }
604 | | }
605 | |
606 | | emit GmxPositionCallbackCalled(requestKey, true);
607 | | // Consider emitting an event that shows the current leverage value later
608 | | }
609 | |
610 | | /**
611 | | * @notice Callback function triggered when an order execution on GMX is canceled due to an error.
612 | | * @param requestKey The request key of the executed order.
613 | | * @param orderType The type of order.
614 | | * @param orderResultData The result data of the order execution.
615 | | */
616 | | function afterOrderCancellation(
617 | | bytes32 requestKey,
618 | | Order.OrderType orderType,
619 | | IGmxUtils.OrderResultData memory orderResultData
620 | | ) external virtual {
621 | | require(msg.sender == address(gmxUtils), "invalid caller");
622 | | _gmxLock = false;
623 | | if (orderResultData.isSettle) {
624 | | // Retry settle action.
625 | | nextAction.selector = NextActionSelector.SETTLE_ACTION;
626 | | } else if (orderType == Order.OrderType.MarketSwap) {
627 | | // If GMX swap fails, retry in the next action.
628 | | nextAction.selector = NextActionSelector.SWAP_ACTION;
629 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken
630 | | nextAction.data = abi.encode(
631 | | swapProgressData.remaining,
632 | | swapProgressData.isCollateralToIndex
633 | | );
634 | | } else {
635 | | if (flow == FLOW.DEPOSIT) {
636 | | nextAction.selector = NextActionSelector.INCREASE_ACTION;
637 | | nextAction.data = abi.encode(beenLong, leverage);
638 | | } else if (flow == FLOW.WITHDRAW) {
639 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
640 | | } else {
641 | | // If signal change fails, the offchain script starts again from the current status.
642 | | delete flowData;
643 | | flow = FLOW.NONE;
644 | | }
645 | | }
646 | | emit GmxPositionCallbackCalled(requestKey, false);
647 | | }
648 | |
649 | | function afterOrderFrozen(
650 | | bytes32 key,
651 | | Order.OrderType,
652 | | bool,
653 | | bytes32
654 | | ) external {}
655 | |
656 | | //////////////////////////////
657 | | //// View Functions ////
658 | | //////////////////////////////
659 | |
660 | | /**
661 | | * @notice
662 | | * return total value of vault in terms of collteral token
663 | | * @param prices gmx price data of market tokens that is from gmx api call
664 | | */
665 | | function totalAmount(
666 | | MarketPrices memory prices
667 | | ) external view returns (uint256) {
668 | | return _totalAmount(prices);
669 | | }
670 | |
671 | | /**
672 | | * @notice
673 | | * get the current gmx position information.
674 | | */
675 | * | function getPositionInfo(
676 | | MarketPrices memory prices
677 | | )
678 | | external
679 | | view
680 | * | returns (address, address, uint256, uint256, uint256, uint256, bool)
681 | | {
682 | * | IGmxUtils.PositionData memory positionData = gmxUtils.getPositionInfo(
683 | * | curPositionKey,
684 | * | prices
685 | | );
686 | * | return (
687 | * | market,
688 | * | address(collateralToken),
689 | * | positionData.sizeInUsd,
690 | * | positionData.sizeInTokens,
691 | * | positionData.collateralAmount,
692 | * | positionData.netValue,
693 | * | positionData.isLong
694 | | );
695 | | }
696 | |
697 | | /**
698 | | * @notice
699 | | * get all deposit ids of a user
700 | | * @param user address of a user
701 | | */
702 | * | function getUserDeposits(
703 | | address user
704 | * | ) external view returns (uint256[] memory depositIds) {
705 | * | uint256 length = EnumerableSet.length(userDeposits[user]);
706 | * | depositIds = new uint256[](length);
707 | * | for (uint8 i = 0; i < length; ) {
708 | * | depositIds[i] = EnumerableSet.at(userDeposits[user], i);
709 | | unchecked {
710 | * | i = i + 1;
711 | | }
712 | | }
713 | | }
714 | |
715 | | /**
716 | | * @notice
717 | | * get the estimated execution fee amount to run deposit or withdrawal
718 | | */
719 | * | function getExecutionGasLimit(
720 | | bool isDeposit
721 | * | ) public view returns (uint256 minExecutionGasLimit) {
722 | * | if (positionIsClosed == false) {
723 | * | if (_isLongOneLeverage(beenLong, leverage)) {
724 | * | minExecutionGasLimit = gmxUtils.getExecutionGasLimit(
725 | * | Order.OrderType.MarketSwap,
726 | * | callbackGasLimit
727 | | );
728 | | } else {
729 | * | if (isDeposit) {
730 | * | minExecutionGasLimit = gmxUtils.getExecutionGasLimit(
731 | * | Order.OrderType.MarketIncrease,
732 | * | callbackGasLimit
733 | | );
734 | | } else {
735 | | // withdraw action has 2 gmx call parts: settle + decrease position
736 | * | minExecutionGasLimit =
737 | * | gmxUtils.getExecutionGasLimit(
738 | * | Order.OrderType.MarketDecrease,
739 | * | callbackGasLimit
740 | | ) *
741 | * | 2;
742 | | }
743 | | }
744 | | }
745 | | }
746 | |
747 | | /**
748 | | * @notice
749 | | * check if there is the next action
750 | | */
751 | | function isNextAction() external view returns (NextActionSelector) {
752 | | if (_gmxLock) {
753 | | return NextActionSelector.NO_ACTION;
754 | | } else if (nextAction.selector != NextActionSelector.NO_ACTION) {
755 | | return nextAction.selector;
756 | | } else if (positionIsClosed == false && _isFundIdle()) {
757 | | return NextActionSelector.COMPOUND_ACTION;
758 | | } else {
759 | | return NextActionSelector.NO_ACTION;
760 | | }
761 | | }
762 | |
763 | | /**
764 | | * @notice Checks if the contract is currently busy.
765 | | * @return bool Returns true if the contract is busy, false otherwise.
766 | | */
767 | * | function isBusy() external view returns (bool) {
768 | * | return flow != FLOW.NONE;
769 | | }
770 | |
771 | | /**
772 | | * @notice Checks if the GMX lock is currently active.
773 | | * @return bool Returns true if the GMX lock is active, false otherwise.
774 | | */
775 | * | function isLock() external view returns (bool) {
776 | * | return _gmxLock;
777 | | }
778 | |
779 | | /**
780 | | * @notice Sets the keeper address.
781 | | * @param _keeper The address of the new keeper.
782 | | */
783 | | function setKeeper(address _keeper) external onlyOwner {
784 | | require(_keeper != address(0), "zero address");
785 | | keeper = _keeper;
786 | | }
787 | |
788 | | /**
789 | | * @notice Sets the treasury address.
790 | | * @param _treasury The address of the new treasury.
791 | | */
792 | | function setTreasury(address _treasury) external onlyOwner {
793 | | require(_treasury != address(0), "zero address");
794 | | treasury = _treasury;
795 | | }
796 | |
797 | | function setMinDepositAmount(uint256 _minDepositAmount) external onlyOwner {
798 | | minDepositAmount = _minDepositAmount;
799 | | }
800 | |
801 | | /**
802 | | * @notice Sets the maximum deposit amount.
803 | | * @param _maxDepositAmount The new maximum deposit amount.
804 | | */
805 | | function setMaxDepositAmount(uint256 _maxDepositAmount) external onlyOwner {
806 | | maxDepositAmount = _maxDepositAmount;
807 | | }
808 | |
809 | | /**
810 | | * @notice Sets the minimum ETH balance.
811 | | * @param _minEth The new minimum ETH balance.
812 | | */
813 | | function setMinEth(uint256 _minEth) external onlyOwner {
814 | | require(_minEth > 0, "minimum");
815 | | minEth = _minEth;
816 | | }
817 | |
818 | | /**
819 | | * @notice Sets the callback gas limit.
820 | | * @param _callbackGasLimit The new callback gas limit.
821 | | */
822 | | function setCallbackGasLimit(uint256 _callbackGasLimit) external onlyOwner {
823 | | require(_callbackGasLimit > 0, "zero value");
824 | | callbackGasLimit = _callbackGasLimit;
825 | | }
826 | |
827 | | /**
828 | | * @notice Sets the lock time.
829 | | * @param _lockTime The new lock time.
830 | | */
831 | | function setLockTime(uint256 _lockTime) external onlyOwner {
832 | | require(_lockTime > 0, "zero value");
833 | | lockTime = _lockTime;
834 | | }
835 | |
836 | | /**
837 | | * @notice Sets the deposit paused state.
838 | | * @param _depositPaused If true, deposits are paused; if false, deposits are active.
839 | | */
840 | | function setDepositPaused(bool _depositPaused) external onlyOwner {
841 | | depositPaused = _depositPaused;
842 | | }
843 | |
844 | | //////////////////////////////
845 | | //// Internal Functions ////
846 | | //////////////////////////////
847 | |
848 | | /**
849 | | * @notice this function is an end of deposit flow.
850 | | * @dev should update all necessary global state variables
851 | | *
852 | | * @param depositId `depositId` of mint operation
853 | | * @param amount actual deposit amount. if `_isLongOneLeverage` is `true`, amount of `indexToken`, or amount of `collateralToken`
854 | | */
855 | * | function _mint(uint256 depositId, uint256 amount, bool refundFee) internal {
856 | * | uint256 _shares;
857 | * | if (totalShares == 0) {
858 | * | _shares = depositInfo[depositId].amount * 1e8;
859 | * | } else {
860 | * | uint256 totalAmountBefore;
861 | |
862 | * | if (
863 | * | positionIsClosed == false &&
864 | * | _isLongOneLeverage(beenLong, leverage)
865 | | ) {
866 | * | totalAmountBefore =
867 | * | IERC20(indexToken).balanceOf(address(this)) -
868 | * | amount;
869 | | } else {
870 | * | totalAmountBefore = _totalAmount(marketPrices) - amount;
871 | | }
872 | * | _shares = (amount * totalShares) / totalAmountBefore;
873 | | }
874 | * | depositInfo[depositId].shares = _shares;
875 | * | totalShares = totalShares + _shares;
876 | |
877 | * | if (refundFee) {
878 | | uint256 usedFee = callbackGasLimit * tx.gasprice;
879 | | if (depositInfo[counter].executionFee > usedFee) {
880 | | IGmxUtils(gmxUtils).refundExecutionFee(
881 | | depositInfo[counter].owner,
882 | | depositInfo[counter].executionFee - usedFee
883 | | );
884 | | }
885 | | }
886 | |
887 | * | emit Minted(depositId, depositInfo[depositId].owner, _shares, amount);
888 | | }
889 | |
890 | | /**
891 | | * burn shares corresponding to `depositId`
892 | | * @param depositId `depositId` to burn
893 | | */
894 | * | function _burn(uint256 depositId) internal {
895 | * | EnumerableSet.remove(
896 | * | userDeposits[depositInfo[depositId].owner],
897 | * | depositId
898 | | );
899 | * | totalShares = totalShares - depositInfo[depositId].shares;
900 | * | delete depositInfo[depositId];
901 | | }
902 | |
903 | | /**
904 | | * @notice
905 | | * update the market price from gmx dataStore contract at the moment of gmx callback
906 | | */
907 | * | function _updateMarketPrice() internal {
908 | * | marketPrices = gmxUtils.getMarketPrices(market);
909 | | }
910 | |
911 | | /**
912 | | * @notice
913 | | * Any excess execution fee from GMX call is not refunded to the user.
914 | | */
915 | * | function _payExecutionFee(uint256 depositId) internal {
916 | * | bool isDeposit = (flow == FLOW.DEPOSIT);
917 | * | uint256 minExecutionFee = getExecutionGasLimit(isDeposit) * tx.gasprice;
918 | |
919 | * | require(msg.value >= minExecutionFee, "insufficient execution fee");
920 | * | if (msg.value > 0) {
921 | * | payable(address(gmxUtils)).transfer(msg.value);
922 | * | depositInfo[depositId].executionFee = msg.value;
923 | | }
924 | | }
925 | |
926 | | /**
927 | | * @notice Calculates the total value of the vault in terms of collateral token.
928 | | * @param prices GMX price data of market tokens from GMX API call.
929 | | * @return The total value of the vault in terms of collateral token.
930 | | */
931 | * | function _totalAmount(
932 | | MarketPrices memory prices
933 | * | ) internal view returns (uint256) {
934 | * | IGmxUtils.PositionData memory positionData = gmxUtils.getPositionInfo(
935 | * | curPositionKey,
936 | * | prices
937 | | );
938 | * | uint256 total = (IERC20(indexToken).balanceOf(address(this)) *
939 | * | prices.indexTokenPrice.min) /
940 | * | prices.shortTokenPrice.min +
941 | * | collateralToken.balanceOf(address(this)) +
942 | * | positionData.netValue /
943 | * | prices.shortTokenPrice.min;
944 | * | return total;
945 | | }
946 | |
947 | | /**
948 | | * @notice Checks if the contract has idle collateral funds that meet the minimum deposit amount.
949 | | * @return bool Returns true if the idle collateral funds are greater than or equal to the minimum deposit amount, false otherwise.
950 | | */
951 | * | function _isFundIdle() internal view returns (bool) {
952 | * | uint256 balance = collateralToken.balanceOf(address(this));
953 | * | if (balance >= minDepositAmount) {
954 | * | return true;
955 | | } else {
956 | * | return false;
957 | | }
958 | | }
959 | |
960 | | /**
961 | | * @notice Creates an increase position request.
962 | | * @dev We register position information with GMX peripheral contracts to open perp positions.
963 | | * This function doesn't open the position actually; it just registers the request of creating position.
964 | | * The actual opening/closing is done by a keeper of the GMX vault.
965 | | * @param _isLong If true, the position is long; if false, the position is short.
966 | | * @param _leverage The leverage value.
967 | | */
968 | | function _createIncreasePosition(
969 | | bool _isLong,
970 | | uint256 _leverage,
971 | | uint256 acceptablePrice
972 | | ) internal virtual gmxLock {
973 | | //NOTE: changed by fuzzer
974 | | // Check available amounts to open positions
975 | | uint256 amountIn;
976 | | if (flow == FLOW.DEPOSIT) {
977 | | amountIn = depositInfo[counter].amount;
978 | | uint256 total = _totalAmount(marketPrices) - amountIn;
979 | | flowData = abi.encode(total);
980 | | } else {
981 | | amountIn = collateralToken.balanceOf(address(this));
982 | | }
983 | |
984 | | Order.OrderType orderType = Order.OrderType.MarketIncrease;
985 | | collateralToken.safeTransfer(address(gmxUtils), amountIn);
986 | | uint256 sizeDelta = (marketPrices.shortTokenPrice.max *
987 | | amountIn *
988 | | _leverage) / BASIS_POINTS_DIVISOR;
989 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
990 | | market: market,
991 | | indexToken: indexToken,
992 | | initialCollateralToken: address(collateralToken),
993 | | swapPath: new address[](0),
994 | | isLong: _isLong,
995 | | sizeDeltaUsd: sizeDelta,
996 | | initialCollateralDeltaAmount: 0,
997 | | amountIn: amountIn,
998 | | callbackGasLimit: callbackGasLimit,
999 | | acceptablePrice: acceptablePrice,
1000 | | minOutputAmount: 0
1001 | | });
1002 | | _gmxLock = true;
1003 | | gmxUtils.createOrder(orderType, orderData);
1004 | | }
1005 | |
1006 | | /**
1007 | | * @notice Creates a decrease position request.
1008 | | * @dev We register position information with GMX peripheral contracts to open perp positions.
1009 | | * This function doesn't close the position actually; it just registers the request of creating position.
1010 | | * The actual opening/closing is done by a keeper of the GMX vault.
1011 | | * @param collateralDeltaAmount The token amount of collateral to withdraw.
1012 | | * @param sizeDeltaInUsd The USD value of the change in position size (decimals is 30).
1013 | | * @param _isLong If true, the position is long; if false, the position is short.
1014 | | */
1015 | | function _createDecreasePosition(
1016 | | uint256 collateralDeltaAmount,
1017 | | uint256 sizeDeltaInUsd,
1018 | | bool _isLong,
1019 | | uint256 acceptablePrice
1020 | | ) internal virtual gmxLock {
1021 | | address[] memory swapPath;
1022 | | Order.OrderType orderType = Order.OrderType.MarketDecrease;
1023 | | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey);
1024 | | if (
1025 | | sizeDeltaInUsd == 0 ||
1026 | | gmxUtils.willPositionCollateralBeSufficient(
1027 | | marketPrices,
1028 | | curPositionKey,
1029 | | market,
1030 | | _isLong,
1031 | | sizeDeltaInUsd
1032 | | )
1033 | | ) {
1034 | | sizeDeltaInUsd = sizeInUsd;
1035 | | }
1036 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
1037 | | market: market,
1038 | | indexToken: indexToken,
1039 | | initialCollateralToken: address(collateralToken),
1040 | | swapPath: swapPath,
1041 | | isLong: _isLong,
1042 | | sizeDeltaUsd: sizeDeltaInUsd,
1043 | | initialCollateralDeltaAmount: collateralDeltaAmount,
1044 | | amountIn: 0,
1045 | | callbackGasLimit: callbackGasLimit,
1046 | | acceptablePrice: acceptablePrice,
1047 | | minOutputAmount: 0
1048 | | });
1049 | | _gmxLock = true;
1050 | | gmxUtils.createOrder(orderType, orderData);
1051 | | }
1052 | |
1053 | | /**
1054 | | * @notice Settles all pending fees (borrowing fee, negative funding fee) against collateral
1055 | | * to process withdrawal requests correctly.
1056 | | * @dev GMX applies all pending fees against collateral when updating the position, which can
1057 | | * result that the current withdrawer suffers all fees of entire position.
1058 | | * This function calls `settle` to pay out fees against collateral so that fee deduction
1059 | | * from GMX positions is ignored in the withdrawal process.
1060 | | */
1061 | * | function _settle() internal {
1062 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
1063 | * | market: market,
1064 | * | indexToken: indexToken,
1065 | * | initialCollateralToken: address(collateralToken),
1066 | * | swapPath: new address[](0),
1067 | * | isLong: beenLong,
1068 | * | sizeDeltaUsd: 0,
1069 | * | initialCollateralDeltaAmount: 0,
1070 | * | amountIn: 0,
1071 | * | callbackGasLimit: callbackGasLimit,
1072 | * | acceptablePrice: 0,
1073 | * | minOutputAmount: 0
1074 | | });
1075 | * | _gmxLock = true;
1076 | * | gmxUtils.settle(orderData);
1077 | | }
1078 | |
1079 | | /**
1080 | | * @dev Swap data is an array of swap data and is passed from an off-chain script.
1081 | | * It could contain only Paraswap data, GMX swap data, or both of them.
1082 | | * If both are included, the first element of the array should always be Paraswap.
1083 | | * @param metadata Bytes array that includes swap data.
1084 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`.
1085 | | * @return completed If true, the swap action is completed; if false, the swap action will continue.
1086 | | */
1087 | * | function _runSwap(
1088 | | bytes[] memory metadata,
1089 | | bool isCollateralToIndex
1090 | * | ) internal returns (bool completed) {
1091 | * | require(metadata.length > 0, "swap data missing");
1092 | * | if (metadata.length == 2) {
1093 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode(
1094 | * | metadata[0],
1095 | | (PROTOCOL, bytes)
1096 | | );
1097 | * | require(_protocol == PROTOCOL.DEX, "invalid swap data");
1098 | * | swapProgressData.swapped =
1099 | * | swapProgressData.swapped +
1100 | * | _doDexSwap(data, isCollateralToIndex);
1101 | |
1102 | * | (_protocol, data) = abi.decode(metadata[1], (PROTOCOL, bytes));
1103 | * | require(_protocol == PROTOCOL.GMX, "invalid swap data");
1104 | |
1105 | * | _doGmxSwap(data, isCollateralToIndex);
1106 | * | return false;
1107 | | } else {
1108 | * | require(metadata.length == 1, "invalid swap data");
1109 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode(
1110 | * | metadata[0],
1111 | | (PROTOCOL, bytes)
1112 | | );
1113 | * | if (_protocol == PROTOCOL.DEX) {
1114 | | uint256 outputAmount = _doDexSwap(data, isCollateralToIndex);
1115 | |
1116 | | // update global state
1117 | | if (flow == FLOW.DEPOSIT) {
1118 | | // last `depositId` equals with `counter` because another deposit is not allowed before previous deposit is completely processed
1119 | | _mint(
1120 | | counter,
1121 | | outputAmount + swapProgressData.swapped,
1122 | | true
1123 | | );
1124 | | } else if (flow == FLOW.WITHDRAW) {
1125 | | _handleReturn(
1126 | | outputAmount + swapProgressData.swapped,
1127 | | false,
1128 | | true
1129 | | );
1130 | | } else {
1131 | | // in the flow of SIGNAL_CHANGE, if `isCollateralToIndex` is true, it is opening position, or closing position
1132 | | _updateState(
1133 | | !isCollateralToIndex,
1134 | | BASIS_POINTS_DIVISOR,
1135 | | isCollateralToIndex
1136 | | );
1137 | | }
1138 | |
1139 | | return true;
1140 | | } else {
1141 | * | _doGmxSwap(data, isCollateralToIndex);
1142 | * | return false;
1143 | | }
1144 | | }
1145 | | }
1146 | |
1147 | | /**
1148 | | * @dev Executes a DEX swap using Paraswap.
1149 | | * @param data Swap transaction data.
1150 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`.
1151 | | * @return outputAmount The amount of output tokens received from the swap.
1152 | | */
1153 | | function _doDexSwap(
1154 | | bytes memory data,
1155 | | bool isCollateralToIndex
1156 | | ) internal virtual returns (uint256 outputAmount) {
1157 | | //NOTE: changed by fuzzer
1158 | | (address to, uint256 amount, bytes memory callData) = abi.decode(
1159 | | data,
1160 | | (address, uint256, bytes)
1161 | | );
1162 | | IERC20 inputToken;
1163 | | IERC20 outputToken;
1164 | | if (isCollateralToIndex) {
1165 | | inputToken = collateralToken;
1166 | | outputToken = IERC20(indexToken);
1167 | | } else {
1168 | | inputToken = IERC20(indexToken);
1169 | | outputToken = collateralToken;
1170 | | }
1171 | | uint256 balBefore = outputToken.balanceOf(address(this));
1172 | | ParaSwapUtils.swap(to, callData);
1173 | | outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore;
1174 | | emit DexSwap(
1175 | | address(inputToken),
1176 | | amount,
1177 | | address(outputToken),
1178 | | outputAmount
1179 | | );
1180 | | }
1181 | |
1182 | | /**
1183 | | * @dev Executes a GMX swap.
1184 | | * @param data Swap transaction data.
1185 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`.
1186 | | */
1187 | | function _doGmxSwap(
1188 | | bytes memory data,
1189 | | bool isCollateralToIndex
1190 | | ) internal virtual {
1191 | | Order.OrderType orderType = Order.OrderType.MarketSwap;
1192 | | (
1193 | | address[] memory gPath,
1194 | | uint256 amountIn,
1195 | | uint256 minOutputAmount
1196 | | ) = abi.decode(data, (address[], uint256, uint256));
1197 | | swapProgressData.remaining = amountIn;
1198 | | swapProgressData.isCollateralToIndex = isCollateralToIndex;
1199 | |
1200 | | address tokenIn;
1201 | | if (isCollateralToIndex) {
1202 | | tokenIn = address(collateralToken);
1203 | | } else {
1204 | | tokenIn = address(indexToken);
1205 | | }
1206 | | IERC20(tokenIn).safeTransfer(address(gmxUtils), amountIn);
1207 | |
1208 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
1209 | | market: address(0),
1210 | | indexToken: address(0),
1211 | | initialCollateralToken: tokenIn,
1212 | | swapPath: gPath,
1213 | | isLong: isCollateralToIndex, // this param has no meaning in swap order, but uses it to see the swap direction
1214 | | sizeDeltaUsd: 0,
1215 | | initialCollateralDeltaAmount: 0,
1216 | | amountIn: amountIn,
1217 | | callbackGasLimit: callbackGasLimit,
1218 | | acceptablePrice: 0,
1219 | | minOutputAmount: minOutputAmount
1220 | | });
1221 | | _gmxLock = true;
1222 | | gmxUtils.createOrder(orderType, orderData);
1223 | | }
1224 | |
1225 | | /**
1226 | | * @notice Handles the internal withdrawal process for a given deposit ID.
1227 | | * @dev This function calculates the share of the withdrawal, handles the swap if necessary,
1228 | | * and updates the position accordingly.
1229 | | * @param depositId The ID of the deposit to withdraw.
1230 | | */
1231 | * | function _withdraw(uint256 depositId, bytes memory metadata) internal {
1232 | * | uint256 shares = depositInfo[depositId].shares;
1233 | * | require(shares > 0, "zero value");
1234 | |
1235 | * | if (positionIsClosed) {
1236 | * | _handleReturn(0, true, false);
1237 | * | } else if (_isLongOneLeverage(beenLong, leverage)) {
1238 | | // beenLong && leverage == BASIS_POINTS_DIVISOR
1239 | * | uint256 swapAmount = (IERC20(indexToken).balanceOf(address(this)) *
1240 | * | shares) / totalShares;
1241 | * | nextAction.selector = NextActionSelector.SWAP_ACTION;
1242 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken
1243 | * | nextAction.data = abi.encode(swapAmount, false);
1244 | * | } else {
1245 | * | IGmxUtils.PositionData memory positionData = gmxUtils
1246 | * | .getPositionInfo(curPositionKey, marketPrices);
1247 | * | uint256 collateralDeltaAmount = (positionData.collateralAmount *
1248 | * | shares) / totalShares;
1249 | * | uint256 sizeDeltaInUsd = (positionData.sizeInUsd * shares) /
1250 | * | totalShares;
1251 | | // we always charge the position fee of negative price impact case.
1252 | * | uint256 feeAmount = gmxUtils.getPositionFeeUsd(
1253 | * | market,
1254 | * | sizeDeltaInUsd,
1255 | * | false
1256 | * | ) / marketPrices.shortTokenPrice.max;
1257 | * | int256 pnl = gmxUtils.getPnl(
1258 | * | curPositionKey,
1259 | * | marketPrices,
1260 | * | sizeDeltaInUsd
1261 | | );
1262 | * | if (pnl < 0) {
1263 | * | collateralDeltaAmount =
1264 | * | collateralDeltaAmount -
1265 | * | feeAmount -
1266 | * | uint256(-pnl) /
1267 | * | marketPrices.shortTokenPrice.max;
1268 | | } else {
1269 | * | collateralDeltaAmount = collateralDeltaAmount - feeAmount;
1270 | | }
1271 | * | uint256 acceptablePrice = abi.decode(metadata, (uint256));
1272 | * | _createDecreasePosition(
1273 | * | collateralDeltaAmount,
1274 | * | sizeDeltaInUsd,
1275 | * | beenLong,
1276 | * | acceptablePrice
1277 | | );
1278 | | }
1279 | | }
1280 | |
1281 | | /**
1282 | | * @notice this function is an end of withdrawal flow.
1283 | | * @dev should update all necessary global state variables
1284 | | *
1285 | | * @param withdrawn amount of token withdrawn from the position
1286 | | * @param positionClosed true when position is closed completely by withdrawing all funds, or false
1287 | | */
1288 | * | function _handleReturn(
1289 | | uint256 withdrawn,
1290 | | bool positionClosed,
1291 | | bool refundFee
1292 | * | ) internal {
1293 | * | (uint256 depositId, ) = abi.decode(flowData, (uint256, address));
1294 | * | uint256 shares = depositInfo[depositId].shares;
1295 | * | uint256 amount;
1296 | * | if (positionClosed) {
1297 | * | amount =
1298 | * | (collateralToken.balanceOf(address(this)) * shares) /
1299 | * | totalShares;
1300 | * | } else {
1301 | * | uint256 balanceBeforeWithdrawal = collateralToken.balanceOf(
1302 | * | address(this)
1303 | * | ) - withdrawn;
1304 | * | amount =
1305 | * | withdrawn +
1306 | * | (balanceBeforeWithdrawal * shares) /
1307 | * | totalShares;
1308 | | }
1309 | * | if (amount > 0) {
1310 | * | _transferToken(depositId, amount);
1311 | | }
1312 | * | emit Burned(
1313 | * | depositId,
1314 | * | depositInfo[depositId].recipient,
1315 | * | depositInfo[depositId].shares,
1316 | * | amount
1317 | | );
1318 | * | _burn(depositId);
1319 | |
1320 | * | if (refundFee) {
1321 | | uint256 usedFee = callbackGasLimit * tx.gasprice;
1322 | | if (depositInfo[depositId].executionFee > usedFee) {
1323 | | IGmxUtils(gmxUtils).refundExecutionFee(
1324 | | depositInfo[depositId].owner,
1325 | | depositInfo[depositId].executionFee - usedFee
1326 | | );
1327 | | }
1328 | | }
1329 | |
1330 | | // update global state
1331 | * | delete swapProgressData;
1332 | * | delete flowData;
1333 | * | flow = FLOW.NONE;
1334 | | }
1335 | |
1336 | | /**
1337 | | * @dev Collect fee from the withdraw amount and transfer tokens to the user.
1338 | | * Collect fee only when the user got the profit.
1339 | | */
1340 | * | function _transferToken(uint256 depositId, uint256 amount) internal {
1341 | * | uint256 fee;
1342 | * | if (amount > depositInfo[depositId].amount) {
1343 | * | fee =
1344 | * | ((amount - depositInfo[depositId].amount) * governanceFee) /
1345 | | BASIS_POINTS_DIVISOR;
1346 | | }
1347 | * | if (fee > 0) {
1348 | * | collateralToken.safeTransfer(treasury, fee);
1349 | | }
1350 | |
1351 | * | try
1352 | * | collateralToken.transfer(
1353 | * | depositInfo[depositId].recipient,
1354 | * | amount - fee
1355 | | )
1356 | | {} catch {
1357 | | collateralToken.transfer(treasury, amount - fee);
1358 | | emit TokenTranferFailed(
1359 | | depositInfo[depositId].recipient,
1360 | | amount - fee
1361 | | );
1362 | | }
1363 | * | totalDepositAmount -= depositInfo[depositId].amount;
1364 | |
1365 | * | emit FeeCollected(address(collateralToken), fee);
1366 | | }
1367 | |
1368 | | /**
1369 | | * update global state in every steps of signal change action
1370 | | * @param _positionIsClosed flag whether position is closed or not
1371 | | * @param _leverage leverage value
1372 | | * @param _isLong isLong value
1373 | | */
1374 | * | function _updateState(
1375 | | bool _positionIsClosed,
1376 | | uint256 _leverage,
1377 | | bool _isLong
1378 | | ) internal {
1379 | * | if (flow == FLOW.SIGNAL_CHANGE) {
1380 | * | positionIsClosed = _positionIsClosed;
1381 | * | if (_positionIsClosed == false) {
1382 | * | leverage = _leverage;
1383 | * | beenLong = _isLong;
1384 | | }
1385 | * | emit SignalChanged(!_positionIsClosed, _isLong, _leverage);
1386 | | }
1387 | |
1388 | * | if (nextAction.selector == NextActionSelector.NO_ACTION) {
1389 | * | delete flowData;
1390 | * | flow = FLOW.NONE;
1391 | | }
1392 | * | delete swapProgressData;
1393 | | }
1394 | |
1395 | * | function _finalize(bytes memory data) internal {
1396 | * | if (flow == FLOW.WITHDRAW) {
1397 | * | (
1398 | * | uint256 prevCollateralBalance,
1399 | * | bool positionClosed,
1400 | * | bool refundFee
1401 | * | ) = abi.decode(data, (uint256, bool, bool));
1402 | * | uint256 withdrawn = collateralToken.balanceOf(address(this)) -
1403 | * | prevCollateralBalance;
1404 | * | _handleReturn(withdrawn, positionClosed, refundFee);
1405 | | } else {
1406 | * | delete swapProgressData;
1407 | * | delete flowData;
1408 | * | flow = FLOW.NONE;
1409 | | }
1410 | | }
1411 | |
1412 | | /**
1413 | | * @notice Checks if the position is a long position with 1x leverage.
1414 | | * @param _isLong If true, the position is a 1x long position.
1415 | | * @param _leverage The leverage value to check.
1416 | | * @return bool Returns true if the position is a long position with 1x leverage, false otherwise.
1417 | | */
1418 | * | function _isLongOneLeverage(
1419 | | bool _isLong,
1420 | | uint256 _leverage
1421 | * | ) internal pure returns (bool) {
1422 | * | return _isLong && _leverage == BASIS_POINTS_DIVISOR;
1423 | | }
1424 | |
1425 | | /**
1426 | | * @notice
1427 | | * check available liquidity before create positions
1428 | | */
1429 | | // function _checkPool(bool _isLong, address _indexToken, address _tokenIn, uint256 sizeDelta) internal view {}
1430 | | }
1431 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/PerpetualVaultLens.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
4 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5 | | import "./PerpetualVault.sol";
6 | | import {MockParaSwapUtils} from "./MockParaswapUtils.sol";
7 | | import "./interfaces/IGmxUtils.sol";
8 | |
9 | * | contract PerpetualVaultLens is PerpetualVault, MockParaSwapUtils {
10 | | using SafeERC20 for IERC20;
11 | |
12 | | //@audit ADDED FUZZING VAR
13 | * | bool public cancellationTriggered;
14 | |
15 | * | function _getSwapProgress() public returns (uint, uint) {
16 | * | uint swappedData = swapProgressData.swapped;
17 | * | uint remainingData = swapProgressData.remaining;
18 | | }
19 | |
20 | * | function _getGMXLock() public returns (bool) {
21 | * | return _gmxLock;
22 | | }
23 | |
24 | | function getGmxUtilsAddress() public view returns (address) {
25 | | return address(gmxUtils);
26 | | }
27 | | function getRequestKey(address vault) public returns (bytes32) {
28 | | (bytes32 requestKey, , , ) = IGmxUtils(
29 | | payable(PerpetualVaultLens(vault).getGmxUtilsAddress())
30 | | ).queue();
31 | | }
32 | |
33 | * | function checkForCleanStart() public view returns (bool) {
34 | * | return (uint(nextAction.selector) == 0 &&
35 | * | cancellationTriggered == false); //NOTE: wasn't cancelled for any reason
36 | | }
37 | |
38 | * | function run(
39 | | bool isOpen,
40 | | bool isLong,
41 | | uint256 _leverage,
42 | | MarketPrices memory prices,
43 | | bytes[] memory _swapData
44 | * | ) public override nonReentrant noneFlow onlyKeeper {
45 | * | bool success = _run(isOpen, isLong, _leverage, prices, _swapData);
46 | * | require(success, "run failed");
47 | | }
48 | |
49 | * | function _run(
50 | | bool isOpen,
51 | | bool isLong,
52 | | uint256 _leverage,
53 | | MarketPrices memory prices,
54 | | bytes[] memory metadata
55 | * | ) internal returns (bool success) {
56 | * | require(
57 | * | address(gmxUtils).balance > minEth,
58 | | "lower than minimum eth balance"
59 | | );
60 | * | cancellationTriggered = false; //NOTE: added by fuzzer
61 | |
62 | * | flow = FLOW.SIGNAL_CHANGE;
63 | * | flowData = abi.encode(_leverage, msg.sender);
64 | * | marketPrices = prices;
65 | |
66 | * | if (isOpen) {
67 | * | if (positionIsClosed) {
68 | * | require(_isFundIdle(), "insufficient balance to open position");
69 | * | if (_isLongOneLeverage(isLong, _leverage)) {
70 | * | _runSwap(metadata, true);
71 | * | } else {
72 | |
73 | * | uint256 acceptablePrice = abi.decode(
74 | * | metadata[0],
75 | | (uint256)
76 | | );
77 | * | _createIncreasePosition(isLong, _leverage, acceptablePrice);
78 | | }
79 | | } else {
80 | * | if (beenLong == isLong) {
81 | * | revert("no action needed");
82 | | } else {
83 | | // Close current position first and then open the requested position in the next action
84 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION;
85 | * | nextAction.data = abi.encode(isLong, _leverage);
86 | * | if (_isLongOneLeverage(beenLong, leverage)) {
87 | * | _runSwap(metadata, false);
88 | * | } else {
89 | * | uint256 acceptablePrice = abi.decode(
90 | * | metadata[0],
91 | | (uint256)
92 | | );
93 | * | _createDecreasePosition(
94 | * | 0,
95 | * | 0,
96 | * | beenLong,
97 | * | acceptablePrice
98 | | );
99 | | }
100 | | }
101 | | }
102 | | } else {
103 | * | if (positionIsClosed == false) {
104 | * | if (_isLongOneLeverage(beenLong, leverage)) {
105 | * | _runSwap(metadata, false);
106 | * | } else {
107 | * | uint256 acceptablePrice = abi.decode(
108 | * | metadata[0],
109 | | (uint256)
110 | | );
111 | * | _createDecreasePosition(0, 0, beenLong, acceptablePrice);
112 | | }
113 | | } else {
114 | * | revert("no action needed");
115 | | }
116 | | }
117 | * | return true; //NOTE: added by fuzzer
118 | | }
119 | |
120 | * | function runNextAction(
121 | | MarketPrices memory prices,
122 | | bytes[] memory _swapData
123 | * | ) external override nonReentrant gmxLock onlyKeeper {
124 | * | bool success = _runNextAction(prices, _swapData);
125 | * | require(success, "runNextAction failed");
126 | | }
127 | |
128 | * | function _runNextAction(
129 | | MarketPrices memory prices,
130 | | bytes[] memory metadata
131 | * | ) internal returns (bool success) {
132 | * | cancellationTriggered = false;
133 | |
134 | * | marketPrices = prices;
135 | * | Action memory _nextAction = nextAction;
136 | * | delete nextAction;
137 | |
138 | |
139 | * | if (_nextAction.selector == NextActionSelector.INCREASE_ACTION) {
140 | * | (bool _isLong, uint256 _leverage) = abi.decode(
141 | * | _nextAction.data,
142 | | (bool, uint256)
143 | | );
144 | * | if (_isLongOneLeverage(_isLong, _leverage)) {
145 | * | _runSwap(metadata, true);
146 | * | } else {
147 | | // swap indexToken that could be generated from the last action into collateralToken
148 | | // use only DexSwap
149 | * | if (metadata[1].length > 0) {
150 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode(
151 | | // metadata[0],
152 | * | metadata[1], //@audit changed by fuzzer
153 | | (PROTOCOL, bytes)
154 | | );
155 | * | require(_protocol == PROTOCOL.DEX, "invalid metadata");
156 | * | _doDexSwap(data, false);
157 | | }
158 | * | uint256 acceptablePrice = abi.decode(metadata[0], (uint256));
159 | * | _createIncreasePosition(_isLong, _leverage, acceptablePrice);
160 | | }
161 | * | } else if (_nextAction.selector == NextActionSelector.WITHDRAW_ACTION) {
162 | | // swap indexToken that could be generated from settle action into collateralToken
163 | | // use only DexSwap
164 | * | if (metadata[1].length > 0) {
165 | | (PROTOCOL _protocol, bytes memory data) = abi.decode(
166 | | // metadata[0],
167 | | metadata[1], //@audit changed by fuzzer
168 | | (PROTOCOL, bytes)
169 | | );
170 | | require(_protocol == PROTOCOL.DEX, "invalid metadata");
171 | | _doDexSwap(data, false);
172 | | }
173 | * | (uint256 depositId, ) = abi.decode(flowData, (uint256, address));
174 | |
175 | * | _withdraw(depositId, metadata[0]);
176 | * | } else if (_nextAction.selector == NextActionSelector.SWAP_ACTION) {
177 | * | (, bool isCollateralToIndex) = abi.decode(
178 | * | _nextAction.data,
179 | | (uint256, bool)
180 | | );
181 | * | _runSwap(metadata, isCollateralToIndex);
182 | * | } else if (_nextAction.selector == NextActionSelector.SETTLE_ACTION) {
183 | * | _settle();
184 | * | } else if (_nextAction.selector == NextActionSelector.FINALIZE) {
185 | * | if (metadata.length > 0) {
186 | |
187 | * | _runSwap(metadata, false);
188 | | }
189 | * | _finalize(_nextAction.data);
190 | * | } else if (positionIsClosed == false && _isFundIdle()) {
191 | |
192 | * | flow = FLOW.COMPOUND;
193 | * | if (_isLongOneLeverage(beenLong, leverage)) {
194 | * | _runSwap(metadata, true);
195 | * | } else {
196 | * | uint256 acceptablePrice = abi.decode(metadata[0], (uint256));
197 | * | _createIncreasePosition(beenLong, leverage, acceptablePrice);
198 | | }
199 | | }
200 | * | return true;
201 | | }
202 | |
203 | * | function deposit(
204 | | uint256 amount
205 | * | ) public payable override nonReentrant noneFlow {
206 | | /** INSERTION BY FUZZER*/
207 | * | _updateMarketPrice();
208 | | /** INSERTION BY FUZZER*/
209 | |
210 | * | bool success = _deposit(amount);
211 | * | require(success, "deposit failed");
212 | | }
213 | |
214 | * | function _deposit(uint256 amount) internal returns (bool success) {
215 | * | require(depositPaused == false, "paused");
216 | * | cancellationTriggered = false;
217 | * | flow = FLOW.DEPOSIT;
218 | | // flowData = abi.encode(msg.sender);
219 | * | require(amount >= minDepositAmount, "insufficient amount");
220 | * | require(
221 | * | totalDepositAmount + amount <= maxDepositAmount,
222 | | "exceeds max deposit cap"
223 | | );
224 | * | collateralToken.safeTransferFrom(msg.sender, address(this), amount);
225 | * | counter++;
226 | * | depositInfo[counter] = DepositInfo(
227 | * | amount,
228 | * | 0,
229 | * | msg.sender,
230 | * | 0,
231 | * | block.timestamp,
232 | * | address(0)
233 | | );
234 | * | totalDepositAmount += amount;
235 | * | EnumerableSet.add(userDeposits[msg.sender], counter);
236 | |
237 | * | if (positionIsClosed) {
238 | * | _mint(counter, amount, false);
239 | * | _finalize(hex"");
240 | | } else {
241 | * | _payExecutionFee(counter);
242 | | // mint share token in the NextAction to involve off-chain price data and improve security
243 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION;
244 | * | nextAction.data = abi.encode(beenLong, leverage);
245 | | }
246 | * | return true;
247 | | }
248 | |
249 | * | function withdraw(
250 | | address recipient,
251 | | uint256 depositId
252 | * | ) public payable override nonReentrant noneFlow {
253 | * | bool success = _withdrawFromGamma(recipient, depositId);
254 | | }
255 | |
256 | * | function _withdrawFromGamma(
257 | | address recipient,
258 | | uint256 depositId
259 | * | ) internal returns (bool success) {
260 | * | cancellationTriggered = false;
261 | |
262 | * | flow = FLOW.WITHDRAW;
263 | * | flowData = abi.encode(depositId, msg.sender);
264 | |
265 | * | require(recipient != address(0), "zero address");
266 | * | require(
267 | * | depositInfo[depositId].timestamp + lockTime < block.timestamp,
268 | | "locked"
269 | | );
270 | * | require(
271 | * | EnumerableSet.contains(userDeposits[msg.sender], depositId),
272 | | "not a valid user"
273 | | );
274 | * | require(depositInfo[depositId].shares > 0, "zero share value");
275 | |
276 | * | depositInfo[depositId].recipient = recipient;
277 | * | if (curPositionKey != bytes32(0)) {
278 | * | _payExecutionFee(depositId);
279 | * | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
280 | * | _settle(); // Settles any outstanding fees and updates state before processing withdrawal
281 | | } else {
282 | * | _withdraw(depositId, hex"00");
283 | | }
284 | |
285 | * | return true;
286 | | }
287 | |
288 | * | function _doDexSwap(
289 | | bytes memory data,
290 | | bool isCollateralToIndex
291 | * | ) internal override returns (uint256 outputAmount) {
292 | * | (address to, uint256 amount, bytes memory callData) = abi.decode(
293 | * | data,
294 | | (address, uint256, bytes)
295 | | );
296 | * | IERC20 inputToken;
297 | * | IERC20 outputToken;
298 | * | if (isCollateralToIndex) {
299 | | inputToken = collateralToken;
300 | | outputToken = IERC20(indexToken);
301 | | } else {
302 | * | inputToken = IERC20(indexToken);
303 | * | outputToken = collateralToken;
304 | | }
305 | * | uint256 balBefore = outputToken.balanceOf(address(this));
306 | * | swap(to, callData);
307 | * | outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore;
308 | * | emit DexSwap(
309 | * | address(inputToken),
310 | * | amount,
311 | * | address(outputToken),
312 | * | outputAmount
313 | | );
314 | | }
315 | |
316 | * | function _createIncreasePosition(
317 | | bool _isLong,
318 | | uint256 _leverage,
319 | | uint256 acceptablePrice
320 | * | ) internal override gmxLock {
321 | | // Check available amounts to open positions
322 | * | uint256 amountIn;
323 | * | if (flow == FLOW.DEPOSIT) {
324 | * | amountIn = depositInfo[counter].amount;
325 | * | uint256 total = _totalAmount(marketPrices) - amountIn;
326 | * | flowData = abi.encode(total);
327 | | } else {
328 | * | amountIn = collateralToken.balanceOf(address(this));
329 | | }
330 | |
331 | * | Order.OrderType orderType = Order.OrderType.MarketIncrease;
332 | * | collateralToken.safeTransfer(address(gmxUtils), amountIn);
333 | * | uint256 sizeDelta = (marketPrices.shortTokenPrice.max *
334 | * | amountIn *
335 | * | _leverage) / BASIS_POINTS_DIVISOR;
336 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
337 | * | market: market,
338 | * | indexToken: indexToken,
339 | * | initialCollateralToken: address(collateralToken),
340 | * | swapPath: new address[](0),
341 | * | isLong: _isLong,
342 | * | sizeDeltaUsd: sizeDelta,
343 | * | initialCollateralDeltaAmount: 0,
344 | * | amountIn: amountIn,
345 | * | callbackGasLimit: callbackGasLimit,
346 | * | acceptablePrice: acceptablePrice,
347 | * | minOutputAmount: 0
348 | | });
349 | * | _gmxLock = true;
350 | |
351 | * | try gmxUtils.createOrder(orderType, orderData) {} catch {
352 | * | cancellationTriggered = true;
353 | * | require(cancellationTriggered == false, "Order creation failed");
354 | | }
355 | | }
356 | |
357 | * | function _createDecreasePosition(
358 | | uint256 collateralDeltaAmount,
359 | | uint256 sizeDeltaInUsd,
360 | | bool _isLong,
361 | | uint256 acceptablePrice
362 | * | ) internal override gmxLock {
363 | * | address[] memory swapPath;
364 | * | Order.OrderType orderType = Order.OrderType.MarketDecrease;
365 | * | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey);
366 | * | if (
367 | * | sizeDeltaInUsd == 0 ||
368 | * | gmxUtils.willPositionCollateralBeSufficient(
369 | * | marketPrices,
370 | * | curPositionKey,
371 | * | market,
372 | * | _isLong,
373 | * | sizeDeltaInUsd
374 | | )
375 | | ) {
376 | * | sizeDeltaInUsd = sizeInUsd;
377 | | }
378 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
379 | * | market: market,
380 | * | indexToken: indexToken,
381 | * | initialCollateralToken: address(collateralToken),
382 | * | swapPath: swapPath,
383 | * | isLong: _isLong,
384 | * | sizeDeltaUsd: sizeDeltaInUsd,
385 | * | initialCollateralDeltaAmount: collateralDeltaAmount,
386 | * | amountIn: 0,
387 | * | callbackGasLimit: callbackGasLimit,
388 | * | acceptablePrice: acceptablePrice,
389 | * | minOutputAmount: 0
390 | | });
391 | * | _gmxLock = true;
392 | |
393 | * | try gmxUtils.createOrder(orderType, orderData) {} catch {
394 | * | cancellationTriggered = true;
395 | * | require(cancellationTriggered == false, "Order creation failed");
396 | | }
397 | | }
398 | |
399 | * | function _doGmxSwap(
400 | | bytes memory data,
401 | | bool isCollateralToIndex
402 | * | ) internal override {
403 | * | Order.OrderType orderType = Order.OrderType.MarketSwap;
404 | * | (
405 | * | address[] memory gPath,
406 | * | uint256 amountIn,
407 | * | uint256 minOutputAmount
408 | * | ) = abi.decode(data, (address[], uint256, uint256));
409 | * | swapProgressData.remaining = amountIn;
410 | * | swapProgressData.isCollateralToIndex = isCollateralToIndex;
411 | |
412 | * | address tokenIn;
413 | * | if (isCollateralToIndex) {
414 | * | tokenIn = address(collateralToken);
415 | | } else {
416 | * | tokenIn = address(indexToken);
417 | | }
418 | * | IERC20(tokenIn).safeTransfer(address(gmxUtils), amountIn);
419 | |
420 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({
421 | * | market: address(0),
422 | * | indexToken: address(0),
423 | * | initialCollateralToken: tokenIn,
424 | * | swapPath: gPath,
425 | * | isLong: isCollateralToIndex, // this param has no meaning in swap order, but uses it to see the swap direction
426 | * | sizeDeltaUsd: 0,
427 | * | initialCollateralDeltaAmount: 0,
428 | * | amountIn: amountIn,
429 | * | callbackGasLimit: callbackGasLimit,
430 | * | acceptablePrice: 0,
431 | * | minOutputAmount: minOutputAmount
432 | | });
433 | * | _gmxLock = true;
434 | |
435 | * | try gmxUtils.createOrder(orderType, orderData) {} catch {
436 | * | cancellationTriggered = true;
437 | |
438 | * | require(false, "Order creation failed");
439 | | }
440 | | }
441 | |
442 | * | function afterOrderExecution(
443 | | bytes32 requestKey,
444 | | bytes32 positionKey,
445 | | IGmxUtils.OrderResultData memory orderResultData
446 | | ) external override nonReentrant {
447 | * | require(msg.sender == address(gmxUtils), "invalid caller");
448 | * | _updateMarketPrice();
449 | |
450 | * | _gmxLock = false;
451 | | // If the current action is `settle`
452 | * | if (orderResultData.isSettle) {
453 | * | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
454 | * | emit GmxPositionCallbackCalled(requestKey, true);
455 | | // emit Settled(positiveFundingFeeAmount, negativeFeeAmount);
456 | * | return;
457 | | }
458 | * | if (orderResultData.orderType == Order.OrderType.MarketIncrease) {
459 | * | curPositionKey = positionKey;
460 | * | if (flow == FLOW.DEPOSIT) {
461 | * | uint256 curAmount = _totalAmount(marketPrices);
462 | * | uint256 prevAmount = abi.decode(flowData, (uint256));
463 | * | if (curAmount > prevAmount) {
464 | * | uint256 increased = (curAmount - prevAmount) /
465 | * | marketPrices.shortTokenPrice.max;
466 | * | _mint(counter, increased, false);
467 | | }
468 | * | nextAction.selector = NextActionSelector.FINALIZE;
469 | * | } else {
470 | * | uint256 _leverage;
471 | * | if (flowData.length > 0) {
472 | * | (_leverage, ) = abi.decode(flowData, (uint256, address));
473 | | } else {
474 | * | _leverage = leverage;
475 | | }
476 | * | _updateState(false, _leverage, orderResultData.isLong);
477 | | }
478 | * | } else if (
479 | * | orderResultData.orderType == Order.OrderType.MarketDecrease
480 | * | ) {
481 | |
482 | * | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey);
483 | * | if (sizeInUsd == 0) {
484 | * | curPositionKey = bytes32(0);
485 | | }
486 | * | if (flow == FLOW.WITHDRAW) {
487 | |
488 | * | nextAction.selector = NextActionSelector.FINALIZE;
489 | * | uint256 prevCollateralBalance = collateralToken.balanceOf(
490 | * | address(this)
491 | * | ) - orderResultData.outputAmount;
492 | * | nextAction.data = abi.encode(
493 | * | prevCollateralBalance,
494 | * | sizeInUsd == 0,
495 | * | false
496 | | );
497 | | // _handleReturn(orderResultData.outputAmount, sizeInUsd == 0, false);
498 | | } else {
499 | * | nextAction.selector = NextActionSelector.FINALIZE;
500 | * | _updateState(true, 0, false);
501 | | }
502 | * | } else if (orderResultData.orderType == Order.OrderType.MarketSwap) {
503 | |
504 | * | uint256 outputAmount = orderResultData.outputAmount;
505 | * | if (swapProgressData.isCollateralToIndex) {
506 | * | emit GmxSwap(
507 | * | address(collateralToken),
508 | * | swapProgressData.remaining,
509 | * | indexToken,
510 | * | outputAmount
511 | | );
512 | | } else {
513 | * | emit GmxSwap(
514 | * | indexToken,
515 | * | swapProgressData.remaining,
516 | * | address(collateralToken),
517 | * | outputAmount
518 | | );
519 | | }
520 | |
521 | * | if (flow == FLOW.DEPOSIT) {
522 | * | _mint(counter, outputAmount + swapProgressData.swapped, false);
523 | * | _finalize(hex"");
524 | * | } else if (flow == FLOW.WITHDRAW) {
525 | * | _handleReturn(
526 | * | outputAmount + swapProgressData.swapped,
527 | * | false,
528 | * | false
529 | | );
530 | | } else {
531 | | // Same as if (flow == FLOW.SIGNAL_CHANGE || FLOW.COMPOUND)
532 | * | if (orderResultData.outputToken == indexToken) {
533 | * | _updateState(false, BASIS_POINTS_DIVISOR, true);
534 | | } else {
535 | * | _updateState(true, 0, false);
536 | | }
537 | | }
538 | | }
539 | * | cancellationTriggered = false;
540 | |
541 | * | emit GmxPositionCallbackCalled(requestKey, true);
542 | | // Consider emitting an event that shows the current leverage value later
543 | | }
544 | |
545 | * | function afterOrderCancellation(
546 | | bytes32 requestKey,
547 | | Order.OrderType orderType,
548 | | IGmxUtils.OrderResultData memory orderResultData
549 | | ) external override {
550 | * | require(msg.sender == address(gmxUtils), "invalid caller");
551 | * | _gmxLock = false;
552 | * | if (orderResultData.isSettle) {
553 | | // Retry settle action.
554 | * | nextAction.selector = NextActionSelector.SETTLE_ACTION;
555 | * | } else if (orderType == Order.OrderType.MarketSwap) {
556 | | // If GMX swap fails, retry in the next action.
557 | * | nextAction.selector = NextActionSelector.SWAP_ACTION;
558 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken
559 | * | nextAction.data = abi.encode(
560 | * | swapProgressData.remaining,
561 | * | swapProgressData.isCollateralToIndex
562 | | );
563 | | } else {
564 | * | if (flow == FLOW.DEPOSIT) {
565 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION;
566 | * | nextAction.data = abi.encode(beenLong, leverage);
567 | * | } else if (flow == FLOW.WITHDRAW) {
568 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
569 | | } else {
570 | | // If signal change fails, the offchain script starts again from the current status.
571 | * | delete flowData;
572 | * | flow = FLOW.NONE;
573 | | }
574 | | }
575 | * | cancellationTriggered = true;
576 | |
577 | * | emit GmxPositionCallbackCalled(requestKey, false);
578 | | }
579 | | }
580 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/IGmxUtils.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "../interfaces/gmx/IReader.sol";
5 | |
6 | | interface IGmxUtils {
7 | | struct PositionData {
8 | | uint256 sizeInUsd;
9 | | uint256 sizeInTokens;
10 | | uint256 collateralAmount;
11 | | uint256 netValue;
12 | | bool isLong;
13 | | }
14 | |
15 | | struct OrderData {
16 | | address market;
17 | | address indexToken;
18 | | address initialCollateralToken;
19 | | address[] swapPath;
20 | | bool isLong;
21 | | uint256 sizeDeltaUsd;
22 | | uint256 initialCollateralDeltaAmount;
23 | | uint256 amountIn;
24 | | uint256 callbackGasLimit;
25 | | uint256 acceptablePrice;
26 | | uint256 minOutputAmount;
27 | | }
28 | |
29 | | struct OrderResultData {
30 | | Order.OrderType orderType;
31 | | bool isLong;
32 | | uint256 sizeDeltaUsd;
33 | | address outputToken;
34 | | uint256 outputAmount;
35 | | bool isSettle;
36 | | }
37 | |
38 | | function getMarket(
39 | | address market
40 | | ) external view returns (MarketProps memory);
41 | | function getPositionInfo(
42 | | bytes32 key,
43 | | MarketPrices memory prices
44 | | ) external view returns (PositionData memory);
45 | | function getPnl(
46 | | bytes32 key,
47 | | MarketPrices memory prices,
48 | | uint256 sizeDeltaUsd
49 | | ) external view returns (int256);
50 | | function getPositionFeeUsd(
51 | | address market,
52 | | uint256 sizeDeltaUsd,
53 | | bool forPositiveImpact
54 | | ) external view returns (uint256);
55 | | function getMarketPrices(
56 | | address market
57 | | ) external view returns (MarketPrices memory);
58 | | function getPositionSizeInUsd(
59 | | bytes32 key
60 | | ) external view returns (uint256 sizeInUsd);
61 | | function getExecutionGasLimit(
62 | | Order.OrderType orderType,
63 | | uint256 callbackGasLimit
64 | | ) external view returns (uint256 executionGasLimit);
65 | | function setPerpVault(address perpVault) external;
66 | | function createOrder(
67 | | Order.OrderType orderType,
68 | | OrderData memory orderData
69 | | ) external returns (bytes32);
70 | | function createOrder(
71 | | Order.OrderType orderType,
72 | | IGmxUtils.OrderData memory orderData,
73 | | MarketPrices memory prices,
74 | | bytes memory callbackdata
75 | | ) external returns (bytes32);
76 | | function settle(OrderData memory orderData) external returns (bytes32);
77 | | function cancelOrder() external;
78 | | function claimCollateralRebates(
79 | | address[] memory,
80 | | address[] memory,
81 | | uint256[] memory,
82 | | address
83 | | ) external;
84 | | function refundExecutionFee(address caller, uint256 amount) external;
85 | | function withdrawEth() external returns (uint256);
86 | | function willPositionCollateralBeSufficient(
87 | | MarketPrices memory prices,
88 | | bytes32 positionKey,
89 | | address market,
90 | | bool isLong,
91 | | uint256 sizeDeltaUsd
92 | | ) external view returns (bool);
93 | |
94 | | function queue()
95 | | external
96 | | view
97 | | returns (bytes32, address, uint256, bytes memory); //NOTE: added by fuzzer
98 | | }
99 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/IPerpetualVault.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "./IGmxUtils.sol";
5 | | import "../libraries/Order.sol";
6 | |
7 | | interface IPerpetualVault {
8 | | function deposit(uint256 amount) external;
9 | | function withdraw(address recipient, uint256 amount) external;
10 | | function shares(address account) external view returns (uint256);
11 | | function lookback() external view returns (uint256);
12 | | function name() external view returns (string memory);
13 | | function indexToken() external view returns (address);
14 | | function collateralToken() external view returns (address);
15 | | function isLong() external view returns (bool);
16 | | function isNextAction() external view returns (bool);
17 | | function isLock() external view returns (bool);
18 | | function isBusy() external view returns (bool);
19 | | function claimCollateralRebates(uint256[] memory) external;
20 | | function afterOrderExecution(bytes32 requestKey, bytes32 positionKey, IGmxUtils.OrderResultData memory) external;
21 | | function afterOrderCancellation(bytes32 key, Order.OrderType, IGmxUtils.OrderResultData memory) external;
22 | | }
23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IDataStore.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | interface IDataStore {
6 | | function getUint(bytes32 key) external view returns (uint256);
7 | | function getBool(bytes32 key) external view returns (bool);
8 | | function getAddress(bytes32 key) external view returns (address);
9 | | function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory);
10 | | }
11 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IExchangeRouter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | import "../../libraries/StructData.sol";
6 | |
7 | | interface IExchangeRouter {
8 | | function sendWnt(address receiver, uint256 amount) external payable;
9 | | function sendTokens(
10 | | address token,
11 | | address receiver,
12 | | uint256 amount
13 | | ) external payable;
14 | | function createOrder(
15 | | CreateOrderParams calldata params
16 | | ) external payable returns (bytes32);
17 | | function createOrderFUZZ(
18 | | CreateOrderParams calldata params
19 | | ) external payable returns (bool, bytes32);
20 | | function cancelOrder(bytes32 key) external payable;
21 | | function claimFundingFees(
22 | | address[] memory markets,
23 | | address[] memory tokens,
24 | | address receiver
25 | | ) external returns (uint256[] memory);
26 | | function claimCollateral(
27 | | address[] memory markets,
28 | | address[] memory tokens,
29 | | uint256[] memory timeKeys,
30 | | address receiver
31 | | ) external returns (uint256[] memory);
32 | | }
33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IOrderCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | import "../../libraries/Order.sol";
6 | |
7 | | struct EventLogData {
8 | | AddressItems addressItems;
9 | | UintItems uintItems;
10 | | IntItems intItems;
11 | | BoolItems boolItems;
12 | | Bytes32Items bytes32Items;
13 | | BytesItems bytesItems;
14 | | StringItems stringItems;
15 | | }
16 | |
17 | | struct AddressItems {
18 | | AddressKeyValue[] items;
19 | | AddressArrayKeyValue[] arrayItems;
20 | | }
21 | |
22 | | struct UintItems {
23 | | UintKeyValue[] items;
24 | | UintArrayKeyValue[] arrayItems;
25 | | }
26 | |
27 | | struct IntItems {
28 | | IntKeyValue[] items;
29 | | IntArrayKeyValue[] arrayItems;
30 | | }
31 | |
32 | | struct BoolItems {
33 | | BoolKeyValue[] items;
34 | | BoolArrayKeyValue[] arrayItems;
35 | | }
36 | |
37 | | struct Bytes32Items {
38 | | Bytes32KeyValue[] items;
39 | | Bytes32ArrayKeyValue[] arrayItems;
40 | | }
41 | |
42 | | struct BytesItems {
43 | | BytesKeyValue[] items;
44 | | BytesArrayKeyValue[] arrayItems;
45 | | }
46 | |
47 | | struct StringItems {
48 | | StringKeyValue[] items;
49 | | StringArrayKeyValue[] arrayItems;
50 | | }
51 | |
52 | | struct AddressKeyValue {
53 | | string key;
54 | | address value;
55 | | }
56 | |
57 | | struct AddressArrayKeyValue {
58 | | string key;
59 | | address[] value;
60 | | }
61 | |
62 | | struct UintKeyValue {
63 | | string key;
64 | | uint256 value;
65 | | }
66 | |
67 | | struct UintArrayKeyValue {
68 | | string key;
69 | | uint256[] value;
70 | | }
71 | |
72 | | struct IntKeyValue {
73 | | string key;
74 | | int256 value;
75 | | }
76 | |
77 | | struct IntArrayKeyValue {
78 | | string key;
79 | | int256[] value;
80 | | }
81 | |
82 | | struct BoolKeyValue {
83 | | string key;
84 | | bool value;
85 | | }
86 | |
87 | | struct BoolArrayKeyValue {
88 | | string key;
89 | | bool[] value;
90 | | }
91 | |
92 | | struct Bytes32KeyValue {
93 | | string key;
94 | | bytes32 value;
95 | | }
96 | |
97 | | struct Bytes32ArrayKeyValue {
98 | | string key;
99 | | bytes32[] value;
100 | | }
101 | |
102 | | struct BytesKeyValue {
103 | | string key;
104 | | bytes value;
105 | | }
106 | |
107 | | struct BytesArrayKeyValue {
108 | | string key;
109 | | bytes[] value;
110 | | }
111 | |
112 | | struct StringKeyValue {
113 | | string key;
114 | | string value;
115 | | }
116 | |
117 | | struct StringArrayKeyValue {
118 | | string key;
119 | | string[] value;
120 | | }
121 | |
122 | | // @title IOrderCallbackReceiver
123 | | // @dev interface for an order callback contract
124 | | interface IOrderCallbackReceiver {
125 | | // @dev called after an order execution
126 | | // @param key the key of the order
127 | | // @param order the order that was executed
128 | | function afterOrderExecution(bytes32 key, Order.Props memory order, EventLogData memory eventData) external;
129 | |
130 | | // @dev called after an order cancellation
131 | | // @param key the key of the order
132 | | // @param order the order that was cancelled
133 | | function afterOrderCancellation(bytes32 key, Order.Props memory order, EventLogData memory eventData) external;
134 | |
135 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info
136 | | // @param key the key of the order
137 | | // @param order the order that was frozen
138 | | function afterOrderFrozen(bytes32 key, Order.Props memory order, EventLogData memory eventData) external;
139 | | }
140 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IOrderHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | import "../../libraries/StructData.sol";
6 | |
7 | | interface IOrderHandler {
8 | | function oracle() external view returns (address);
9 | | }
10 | |
11 | | interface IOracle {
12 | | function getPrimaryPrice(address token) external view returns (PriceProps memory);
13 | | }
14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IReader.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | import "./IDataStore.sol";
6 | | import "../../libraries/StructData.sol";
7 | | import "../../libraries/Position.sol";
8 | | import "../../libraries/Order.sol";
9 | |
10 | | interface IReader {
11 | | function getMarket(address dataStore, address key) external view returns (MarketProps memory);
12 | | // function getMarkets(IDataStore dataStore, uint256 start, uint256 end) external view returns (MarketProps[] memory);
13 | | function getPosition(address dataStore, bytes32 key) external view returns (Position.Props memory);
14 | | function getAccountOrders(
15 | | address dataStore,
16 | | address account,
17 | | uint256 start,
18 | | uint256 end
19 | | ) external view returns (Order.Props[] memory);
20 | | function getPositionInfo(
21 | | address dataStore,
22 | | address referralStorage,
23 | | bytes32 positionKey,
24 | | MarketPrices memory prices,
25 | | uint256 sizeDeltaUsd,
26 | | address uiFeeReceiver,
27 | | bool usePositionSizeAsSizeDeltaUsd
28 | | ) external view returns (PositionInfo memory);
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/Order.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | // @title Order
6 | | // @dev Struct for orders
7 | * | library Order {
8 | | using Order for Props;
9 | |
10 | | enum OrderType {
11 | | // @dev MarketSwap: swap token A to token B at the current market price
12 | | // the order will be cancelled if the minOutputAmount cannot be fulfilled
13 | | MarketSwap,
14 | | // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled
15 | | LimitSwap,
16 | | // @dev MarketIncrease: increase position at the current market price
17 | | // the order will be cancelled if the position cannot be increased at the acceptablePrice
18 | | MarketIncrease,
19 | | // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled
20 | | LimitIncrease,
21 | | // @dev MarketDecrease: decrease position at the current market price
22 | | // the order will be cancelled if the position cannot be decreased at the acceptablePrice
23 | | MarketDecrease,
24 | | // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
25 | | LimitDecrease,
26 | | // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
27 | | StopLossDecrease,
28 | | // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met
29 | | Liquidation
30 | | }
31 | |
32 | | // to help further differentiate orders
33 | | enum SecondaryOrderType {
34 | | None,
35 | | Adl
36 | | }
37 | |
38 | | enum DecreasePositionSwapType {
39 | | NoSwap,
40 | | SwapPnlTokenToCollateralToken,
41 | | SwapCollateralTokenToPnlToken
42 | | }
43 | |
44 | | // @dev there is a limit on the number of fields a struct can have when being passed
45 | | // or returned as a memory variable which can cause "Stack too deep" errors
46 | | // use sub-structs to avoid this issue
47 | | // @param addresses address values
48 | | // @param numbers number values
49 | | // @param flags boolean values
50 | | struct Props {
51 | | Addresses addresses;
52 | | Numbers numbers;
53 | | Flags flags;
54 | | }
55 | |
56 | | // @param account the account of the order
57 | | // @param receiver the receiver for any token transfers
58 | | // this field is meant to allow the output of an order to be
59 | | // received by an address that is different from the creator of the
60 | | // order whether this is for swaps or whether the account is the owner
61 | | // of a position
62 | | // for funding fees and claimable collateral, the funds are still
63 | | // credited to the owner of the position indicated by order.account
64 | | // @param callbackContract the contract to call for callbacks
65 | | // @param uiFeeReceiver the ui fee receiver
66 | | // @param market the trading market
67 | | // @param initialCollateralToken for increase orders, initialCollateralToken
68 | | // is the token sent in by the user, the token will be swapped through the
69 | | // specified swapPath, before being deposited into the position as collateral
70 | | // for decrease orders, initialCollateralToken is the collateral token of the position
71 | | // withdrawn collateral from the decrease of the position will be swapped
72 | | // through the specified swapPath
73 | | // for swaps, initialCollateralToken is the initial token sent for the swap
74 | | // @param swapPath an array of market addresses to swap through
75 | | struct Addresses {
76 | | address account;
77 | | address receiver;
78 | | address cancellationReceiver;
79 | | address callbackContract;
80 | | address uiFeeReceiver;
81 | | address market;
82 | | address initialCollateralToken;
83 | | address[] swapPath;
84 | | }
85 | |
86 | | // @param sizeDeltaUsd the requested change in position size
87 | | // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount
88 | | // is the amount of the initialCollateralToken sent in by the user
89 | | // for decrease orders, initialCollateralDeltaAmount is the amount of the position's
90 | | // collateralToken to withdraw
91 | | // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent
92 | | // in for the swap
93 | | // @param orderType the order type
94 | | // @param triggerPrice the trigger price for non-market orders
95 | | // @param acceptablePrice the acceptable execution price for increase / decrease orders
96 | | // @param executionFee the execution fee for keepers
97 | | // @param callbackGasLimit the gas limit for the callbackContract
98 | | // @param minOutputAmount the minimum output amount for decrease orders and swaps
99 | | // note that for decrease orders, multiple tokens could be received, for this reason, the
100 | | // minOutputAmount value is treated as a USD value for validation in decrease orders
101 | | // @param updatedAtBlock the block at which the order was last updated
102 | | struct Numbers {
103 | | OrderType orderType;
104 | | DecreasePositionSwapType decreasePositionSwapType;
105 | | uint256 sizeDeltaUsd;
106 | | uint256 initialCollateralDeltaAmount;
107 | | uint256 triggerPrice;
108 | | uint256 acceptablePrice;
109 | | uint256 executionFee;
110 | | uint256 callbackGasLimit;
111 | | uint256 minOutputAmount;
112 | | uint256 updatedAtBlock;
113 | | uint256 updatedAtTime;
114 | | }
115 | |
116 | | // @param isLong whether the order is for a long or short
117 | | // @param shouldUnwrapNativeToken whether to unwrap native tokens before
118 | | // transferring to the user
119 | | // @param isFrozen whether the order is frozen
120 | | struct Flags {
121 | | bool isLong;
122 | | bool shouldUnwrapNativeToken;
123 | | bool isFrozen;
124 | | bool autoCancel;
125 | | }
126 | | }
127 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/ParaSwapUtils.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6 | | import {console} from "forge-std/Test.sol";
7 | | interface IAugustusSwapper {
8 | | function getTokenTransferProxy() external view returns (address);
9 | | }
10 | |
11 | * | library ParaSwapUtils {
12 | | using SafeERC20 for IERC20;
13 | |
14 | | function swap(address to, bytes memory callData) external {
15 | | _validateCallData(to, callData);
16 | | address approvalAddress = IAugustusSwapper(to).getTokenTransferProxy();
17 | | address fromToken;
18 | | uint256 fromAmount;
19 | | assembly {
20 | | fromToken := mload(add(callData, 68))
21 | | fromAmount := mload(add(callData, 100))
22 | | }
23 | | IERC20(fromToken).safeApprove(approvalAddress, fromAmount);
24 | | (bool success, ) = to.call(callData);
25 | | require(success, "paraswap call reverted");
26 | | }
27 | |
28 | | function _validateCallData(
29 | | address to,
30 | | bytes memory callData
31 | | ) internal view {
32 | | require(
33 | | to == address(0x731a10897d267e19B34503aD902d0A29173Ba4B1), //foundry address
34 | | "invalid paraswap callee"
35 | | );
36 | |
37 | | address receiver;
38 | | assembly {
39 | | receiver := mload(add(callData, 196))
40 | | }
41 | | require(receiver == address(this), "invalid paraswap calldata");
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/Position.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.4;
4 | |
5 | | // @title Position
6 | | // @dev Stuct for positions
7 | | //
8 | | // borrowing fees for position require only a borrowingFactor to track
9 | | // an example on how this works is if the global cumulativeBorrowingFactor is 10020%
10 | | // a position would be opened with borrowingFactor as 10020%
11 | | // after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would
12 | | // owe 5% of the position size as borrowing fees
13 | | // the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs
14 | | // when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's
15 | | // collateral and transferred into the LP pool
16 | | //
17 | | // the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees
18 | | // based on the fiat value of the position sizes
19 | | //
20 | | // for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position
21 | | // claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would
22 | | // only owe 0.05 longToken ($200)
23 | | // this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts
24 | | // to be deducted and to be paid out need to be tracked instead
25 | | //
26 | | // for funding fees, there are four values to consider:
27 | | // 1. long positions with market.longToken as collateral
28 | | // 2. long positions with market.shortToken as collateral
29 | | // 3. short positions with market.longToken as collateral
30 | | // 4. short positions with market.shortToken as collateral
31 | * | library Position {
32 | | // @dev there is a limit on the number of fields a struct can have when being passed
33 | | // or returned as a memory variable which can cause "Stack too deep" errors
34 | | // use sub-structs to avoid this issue
35 | | // @param addresses address values
36 | | // @param numbers number values
37 | | // @param flags boolean values
38 | | struct Props {
39 | | Addresses addresses;
40 | | Numbers numbers;
41 | | Flags flags;
42 | | }
43 | |
44 | | // @param account the position's account
45 | | // @param market the position's market
46 | | // @param collateralToken the position's collateralToken
47 | | struct Addresses {
48 | | address account;
49 | | address market;
50 | | address collateralToken;
51 | | }
52 | |
53 | | // @param sizeInUsd the position's size in USD
54 | | // @param sizeInTokens the position's size in tokens
55 | | // @param collateralAmount the amount of collateralToken for collateral
56 | | // @param borrowingFactor the position's borrowing factor
57 | | // @param fundingFeeAmountPerSize the position's funding fee per size
58 | | // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size
59 | | // for the market.longToken
60 | | // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size
61 | | // for the market.shortToken
62 | | // @param increasedAtBlock the block at which the position was last increased
63 | | // @param decreasedAtBlock the block at which the position was last decreased
64 | | struct Numbers {
65 | | uint256 sizeInUsd;
66 | | uint256 sizeInTokens;
67 | | uint256 collateralAmount;
68 | | uint256 borrowingFactor;
69 | | uint256 fundingFeeAmountPerSize;
70 | | uint256 longTokenClaimableFundingAmountPerSize;
71 | | uint256 shortTokenClaimableFundingAmountPerSize;
72 | | uint256 increasedAtBlock;
73 | | uint256 decreasedAtBlock;
74 | | uint256 increasedAtTime;
75 | | uint256 decreasedAtTime;
76 | | }
77 | |
78 | | // @param isLong whether the position is a long or short
79 | | struct Flags {
80 | | bool isLong;
81 | | }
82 | | }
83 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/StructData.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "./Position.sol";
5 | | import "./Order.sol";
6 | |
7 | | struct MarketProps {
8 | | address marketToken;
9 | | address indexToken;
10 | | address longToken;
11 | | address shortToken;
12 | | }
13 | |
14 | | struct PriceProps {
15 | | uint256 min;
16 | | uint256 max;
17 | | }
18 | |
19 | | struct MarketPrices {
20 | | PriceProps indexTokenPrice;
21 | | PriceProps longTokenPrice;
22 | | PriceProps shortTokenPrice;
23 | | }
24 | |
25 | | struct PositionFees {
26 | | PositionReferralFees referral;
27 | | PositionFundingFees funding;
28 | | PositionBorrowingFees borrowing;
29 | | PositionUiFees ui;
30 | | PriceProps collateralTokenPrice;
31 | | uint256 positionFeeFactor;
32 | | uint256 protocolFeeAmount;
33 | | uint256 positionFeeReceiverFactor;
34 | | uint256 feeReceiverAmount;
35 | | uint256 feeAmountForPool;
36 | | uint256 positionFeeAmountForPool;
37 | | uint256 positionFeeAmount;
38 | | uint256 totalCostAmountExcludingFunding;
39 | | uint256 totalCostAmount;
40 | | }
41 | |
42 | | // @param affiliate the referral affiliate of the trader
43 | | // @param traderDiscountAmount the discount amount for the trader
44 | | // @param affiliateRewardAmount the affiliate reward amount
45 | | struct PositionReferralFees {
46 | | bytes32 referralCode;
47 | | address affiliate;
48 | | address trader;
49 | | uint256 totalRebateFactor;
50 | | uint256 traderDiscountFactor;
51 | | uint256 totalRebateAmount;
52 | | uint256 traderDiscountAmount;
53 | | uint256 affiliateRewardAmount;
54 | | }
55 | |
56 | | struct PositionBorrowingFees {
57 | | uint256 borrowingFeeUsd;
58 | | uint256 borrowingFeeAmount;
59 | | uint256 borrowingFeeReceiverFactor;
60 | | uint256 borrowingFeeAmountForFeeReceiver;
61 | | }
62 | |
63 | | // @param fundingFeeAmount the position's funding fee amount
64 | | // @param claimableLongTokenAmount the negative funding fee in long token that is claimable
65 | | // @param claimableShortTokenAmount the negative funding fee in short token that is claimable
66 | | // @param latestLongTokenFundingAmountPerSize the latest long token funding
67 | | // amount per size for the market
68 | | // @param latestShortTokenFundingAmountPerSize the latest short token funding
69 | | // amount per size for the market
70 | | struct PositionFundingFees {
71 | | uint256 fundingFeeAmount;
72 | | uint256 claimableLongTokenAmount;
73 | | uint256 claimableShortTokenAmount;
74 | | uint256 latestFundingFeeAmountPerSize;
75 | | uint256 latestLongTokenClaimableFundingAmountPerSize;
76 | | uint256 latestShortTokenClaimableFundingAmountPerSize;
77 | | }
78 | |
79 | | struct PositionUiFees {
80 | | address uiFeeReceiver;
81 | | uint256 uiFeeReceiverFactor;
82 | | uint256 uiFeeAmount;
83 | | }
84 | |
85 | | struct ExecutionPriceResult {
86 | | int256 priceImpactUsd;
87 | | uint256 priceImpactDiffUsd;
88 | | uint256 executionPrice;
89 | | }
90 | |
91 | | struct PositionInfo {
92 | | Position.Props position;
93 | | PositionFees fees;
94 | | ExecutionPriceResult executionPriceResult;
95 | | int256 basePnlUsd;
96 | | int256 uncappedBasePnlUsd;
97 | | int256 pnlAfterPriceImpactUsd;
98 | | }
99 | |
100 | | // @param addresses address values
101 | | // @param numbers number values
102 | | // @param orderType for order.orderType
103 | | // @param decreasePositionSwapType for order.decreasePositionSwapType
104 | | // @param isLong for order.isLong
105 | | // @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken
106 | | struct CreateOrderParams {
107 | | CreateOrderParamsAddresses addresses;
108 | | CreateOrderParamsNumbers numbers;
109 | | Order.OrderType orderType;
110 | | Order.DecreasePositionSwapType decreasePositionSwapType;
111 | | bool isLong;
112 | | bool shouldUnwrapNativeToken;
113 | | bool autoCancel;
114 | | bytes32 referralCode;
115 | | }
116 | |
117 | | // @param receiver for order.receiver
118 | | // @param callbackContract for order.callbackContract
119 | | // @param market for order.market
120 | | // @param initialCollateralToken for order.initialCollateralToken
121 | | // @param swapPath for order.swapPath
122 | | struct CreateOrderParamsAddresses {
123 | | address receiver;
124 | | address cancellationReceiver;
125 | | address callbackContract;
126 | | address uiFeeReceiver;
127 | | address market;
128 | | address initialCollateralToken;
129 | | address[] swapPath;
130 | | }
131 | |
132 | | // @param sizeDeltaUsd for order.sizeDeltaUsd
133 | | // @param triggerPrice for order.triggerPrice
134 | | // @param acceptablePrice for order.acceptablePrice
135 | | // @param executionFee for order.executionFee
136 | | // @param callbackGasLimit for order.callbackGasLimit
137 | | // @param minOutputAmount for order.minOutputAmount
138 | | struct CreateOrderParamsNumbers {
139 | | uint256 sizeDeltaUsd;
140 | | uint256 initialCollateralDeltaAmount;
141 | | uint256 triggerPrice;
142 | | uint256 acceptablePrice;
143 | | uint256 executionFee;
144 | | uint256 callbackGasLimit;
145 | | uint256 minOutputAmount;
146 | | }
147 | |
148 | | // following are not from GMX.
149 | |
150 | | enum PROTOCOL {
151 | | DEX,
152 | | GMX
153 | | }
154 | |
155 | | struct lifiSwapData {
156 | | address callTo;
157 | | address approveTo;
158 | | address sendingAssetId;
159 | | address receivingAssetId;
160 | | uint256 fromAmount;
161 | | bytes callData;
162 | | bool requiresDeposit;
163 | | }
164 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/gmx/MarketUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
6 | | import "@openzeppelin/contracts/utils/math/Math.sol";
7 | | import "@openzeppelin/contracts/utils/math/SignedSafeMath.sol";
8 | |
9 | | import "../../interfaces/gmx/IDataStore.sol";
10 | | import "../StructData.sol";
11 | |
12 | | // @title MarketUtils
13 | | // @dev Library for market functions
14 | * | library MarketUtils {
15 | | using SignedSafeMath for int256;
16 | | using SafeCast for int256;
17 | | using SafeCast for uint256;
18 | |
19 | * | uint256 public constant FLOAT_PRECISION = 10 ** 30;
20 | * | bytes32 public constant OPEN_INTEREST = keccak256(abi.encode("OPEN_INTEREST"));
21 | * | bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode("MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER"));
22 | * | bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode("MIN_COLLATERAL_FACTOR"));
23 | |
24 | | struct WillPositionCollateralBeSufficientValues {
25 | | uint256 positionSizeInUsd;
26 | | uint256 positionCollateralAmount;
27 | | int256 realizedPnlUsd;
28 | | int256 openInterestDelta;
29 | | }
30 | |
31 | * | function willPositionCollateralBeSufficient(
32 | | IDataStore dataStore,
33 | | MarketProps memory market,
34 | | MarketPrices memory prices,
35 | | bool isLong,
36 | | WillPositionCollateralBeSufficientValues memory values
37 | * | ) public view returns (bool, int256) {
38 | * | PriceProps memory collateralTokenPrice = prices.shortTokenPrice;
39 | |
40 | * | int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();
41 | |
42 | | // deduct realized pnl if it is negative since this would be paid from
43 | | // the position's collateral
44 | * | if (values.realizedPnlUsd < 0) {
45 | * | remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;
46 | | }
47 | |
48 | * | if (remainingCollateralUsd < 0) {
49 | | return (false, remainingCollateralUsd);
50 | | }
51 | |
52 | | // the min collateral factor will increase as the open interest for a market increases
53 | | // this may lead to previously created limit increase orders not being executable
54 | | //
55 | | // the position's pnl is not factored into the remainingCollateralUsd value, since
56 | | // factoring in a positive pnl may allow the user to manipulate price and bypass this check
57 | | // it may be useful to factor in a negative pnl for this check, this can be added if required
58 | * | uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(
59 | * | dataStore,
60 | * | market,
61 | * | values.openInterestDelta,
62 | * | isLong
63 | | );
64 | |
65 | * | uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);
66 | | // use the minCollateralFactor for the market if it is larger
67 | * | if (minCollateralFactorForMarket > minCollateralFactor) {
68 | * | minCollateralFactor = minCollateralFactorForMarket;
69 | | }
70 | |
71 | * | int256 minCollateralUsdForLeverage = applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();
72 | * | bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;
73 | |
74 | * | return (willBeSufficient, remainingCollateralUsd);
75 | | }
76 | |
77 | | // @dev get the min collateral factor for open interest multiplier
78 | | // @param dataStore DataStore
79 | | // @param market the market to check
80 | | // @param isLong whether it is for the long or short side
81 | * | function getMinCollateralFactorForOpenInterestMultiplier(IDataStore dataStore, address market, bool isLong) internal view returns (uint256) {
82 | * | return dataStore.getUint(minCollateralFactorForOpenInterestMultiplierKey(market, isLong));
83 | | }
84 | |
85 | | // @dev get the min collateral factor for open interest
86 | | // @param dataStore DataStore
87 | | // @param market the market to check
88 | | // @param longToken the long token of the market
89 | | // @param shortToken the short token of the market
90 | | // @param openInterestDelta the change in open interest
91 | | // @param isLong whether it is for the long or short side
92 | * | function getMinCollateralFactorForOpenInterest(
93 | | IDataStore dataStore,
94 | | MarketProps memory market,
95 | | int256 openInterestDelta,
96 | | bool isLong
97 | * | ) internal view returns (uint256) {
98 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
99 | * | openInterest = sumReturnUint256(openInterest, openInterestDelta);
100 | * | uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);
101 | * | return applyFactor(openInterest, multiplierFactor);
102 | | }
103 | |
104 | | // @dev get the open interest of a market
105 | | // @param dataStore DataStore
106 | | // @param market the market to check
107 | | // @param longToken the long token of the market
108 | | // @param shortToken the short token of the market
109 | | function getOpenInterest(
110 | | IDataStore dataStore,
111 | | MarketProps memory market
112 | | ) internal view returns (uint256) {
113 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true);
114 | | uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);
115 | |
116 | | return longOpenInterest + shortOpenInterest;
117 | | }
118 | |
119 | | // @dev get either the long or short open interest for a market
120 | | // @param dataStore DataStore
121 | | // @param market the market to check
122 | | // @param longToken the long token of the market
123 | | // @param shortToken the short token of the market
124 | | // @param isLong whether to get the long or short open interest
125 | | // @return the long or short open interest for a market
126 | * | function getOpenInterest(
127 | | IDataStore dataStore,
128 | | MarketProps memory market,
129 | | bool isLong
130 | * | ) internal view returns (uint256) {
131 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
132 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);
133 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);
134 | |
135 | * | return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;
136 | | }
137 | |
138 | | // @dev the long and short open interest for a market based on the collateral token used
139 | | // @param dataStore DataStore
140 | | // @param market the market to check
141 | | // @param collateralToken the collateral token to check
142 | | // @param isLong whether to check the long or short side
143 | * | function getOpenInterest(
144 | | IDataStore dataStore,
145 | | address market,
146 | | address collateralToken,
147 | | bool isLong,
148 | | uint256 divisor
149 | * | ) internal view returns (uint256) {
150 | * | return dataStore.getUint(openInterestKey(market, collateralToken, isLong)) / divisor;
151 | | }
152 | |
153 | | // this is used to divide the values of getPoolAmount and getOpenInterest
154 | | // if the longToken and shortToken are the same, then these values have to be divided by two
155 | | // to avoid double counting
156 | * | function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {
157 | * | return longToken == shortToken ? 2 : 1;
158 | | }
159 | |
160 | * | function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {
161 | * | if (b > 0) {
162 | | return a + uint256(b);
163 | | }
164 | |
165 | * | return a - uint256(-b);
166 | | }
167 | |
168 | | /**
169 | | * Applies the given factor to the given value and returns the result.
170 | | *
171 | | * @param value The value to apply the factor to.
172 | | * @param factor The factor to apply.
173 | | * @return The result of applying the factor to the value.
174 | | */
175 | * | function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {
176 | * | return Math.mulDiv(value, factor, FLOAT_PRECISION);
177 | | }
178 | |
179 | | // @dev get the min collateral factor
180 | | // @param dataStore DataStore
181 | | // @param market the market to check
182 | * | function getMinCollateralFactor(IDataStore dataStore, address market) internal view returns (uint256) {
183 | * | return dataStore.getUint(minCollateralFactorKey(market));
184 | | }
185 | |
186 | | // @dev key for open interest
187 | | // @param market the market to check
188 | | // @param collateralToken the collateralToken to check
189 | | // @param isLong whether to check the long or short open interest
190 | | // @return key for open interest
191 | * | function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
192 | * | return keccak256(abi.encode(
193 | | OPEN_INTEREST,
194 | * | market,
195 | * | collateralToken,
196 | * | isLong
197 | | ));
198 | | }
199 | |
200 | | // @dev the min collateral factor for open interest multiplier key
201 | | // @param the market for the factor
202 | * | function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {
203 | * | return keccak256(abi.encode(
204 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,
205 | * | market,
206 | * | isLong
207 | | ));
208 | | }
209 | |
210 | | // @dev the min collateral factor key
211 | | // @param the market for the min collateral factor
212 | * | function minCollateralFactorKey(address market) internal pure returns (bytes32) {
213 | * | return keccak256(abi.encode(
214 | | MIN_COLLATERAL_FACTOR,
215 | * | market
216 | | ));
217 | | }
218 | | }
219 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Base.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | import {StdStorage} from "./StdStorage.sol";
5 | | import {Vm, VmSafe} from "./Vm.sol";
6 | |
7 | | abstract contract CommonBase {
8 | | // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
9 | * | address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
10 | | // console.sol and console2.sol work by executing a staticcall to this address.
11 | | address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
12 | | // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
13 | | address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
14 | | // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.
15 | | address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller"))));
16 | | // Address of the test contract, deployed by the DEFAULT_SENDER.
17 | | address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
18 | | // Deterministic deployment address of the Multicall3 contract.
19 | | address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
20 | | // The order of the secp256k1 curve.
21 | | uint256 internal constant SECP256K1_ORDER =
22 | | 115792089237316195423570985008687907852837564279074904382605163141518161494337;
23 | |
24 | | uint256 internal constant UINT256_MAX =
25 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935;
26 | |
27 | | Vm internal constant vm = Vm(VM_ADDRESS);
28 | | StdStorage internal stdstore;
29 | | }
30 | |
31 | | abstract contract TestBase is CommonBase {}
32 | |
33 | | abstract contract ScriptBase is CommonBase {
34 | | VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
35 | | }
36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdAssertions.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | | pragma experimental ABIEncoderV2;
4 | |
5 | | import {Vm} from "./Vm.sol";
6 | |
7 | | abstract contract StdAssertions {
8 | * | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
9 | |
10 | | event log(string);
11 | | event logs(bytes);
12 | |
13 | | event log_address(address);
14 | | event log_bytes32(bytes32);
15 | | event log_int(int256);
16 | | event log_uint(uint256);
17 | | event log_bytes(bytes);
18 | | event log_string(string);
19 | |
20 | | event log_named_address(string key, address val);
21 | | event log_named_bytes32(string key, bytes32 val);
22 | | event log_named_decimal_int(string key, int256 val, uint256 decimals);
23 | | event log_named_decimal_uint(string key, uint256 val, uint256 decimals);
24 | | event log_named_int(string key, int256 val);
25 | | event log_named_uint(string key, uint256 val);
26 | | event log_named_bytes(string key, bytes val);
27 | | event log_named_string(string key, string val);
28 | |
29 | | event log_array(uint256[] val);
30 | | event log_array(int256[] val);
31 | | event log_array(address[] val);
32 | | event log_named_array(string key, uint256[] val);
33 | | event log_named_array(string key, int256[] val);
34 | | event log_named_array(string key, address[] val);
35 | |
36 | | bool private _failed;
37 | |
38 | * | function failed() public view returns (bool) {
39 | * | if (_failed) {
40 | | return _failed;
41 | | } else {
42 | * | return vm.load(address(vm), bytes32("failed")) != bytes32(0);
43 | | }
44 | | }
45 | |
46 | | function fail() internal virtual {
47 | | vm.store(address(vm), bytes32("failed"), bytes32(uint256(1)));
48 | | _failed = true;
49 | | }
50 | |
51 | | function assertTrue(bool data) internal pure virtual {
52 | | vm.assertTrue(data);
53 | | }
54 | |
55 | | function assertTrue(bool data, string memory err) internal pure virtual {
56 | | vm.assertTrue(data, err);
57 | | }
58 | |
59 | | function assertFalse(bool data) internal pure virtual {
60 | | vm.assertFalse(data);
61 | | }
62 | |
63 | | function assertFalse(bool data, string memory err) internal pure virtual {
64 | | vm.assertFalse(data, err);
65 | | }
66 | |
67 | | function assertEq(bool left, bool right) internal pure virtual {
68 | | vm.assertEq(left, right);
69 | | }
70 | |
71 | | function assertEq(bool left, bool right, string memory err) internal pure virtual {
72 | | vm.assertEq(left, right, err);
73 | | }
74 | |
75 | | function assertEq(uint256 left, uint256 right) internal pure virtual {
76 | | vm.assertEq(left, right);
77 | | }
78 | |
79 | | function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual {
80 | | vm.assertEq(left, right, err);
81 | | }
82 | |
83 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
84 | | vm.assertEqDecimal(left, right, decimals);
85 | | }
86 | |
87 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
88 | | vm.assertEqDecimal(left, right, decimals, err);
89 | | }
90 | |
91 | | function assertEq(int256 left, int256 right) internal pure virtual {
92 | | vm.assertEq(left, right);
93 | | }
94 | |
95 | | function assertEq(int256 left, int256 right, string memory err) internal pure virtual {
96 | | vm.assertEq(left, right, err);
97 | | }
98 | |
99 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
100 | | vm.assertEqDecimal(left, right, decimals);
101 | | }
102 | |
103 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
104 | | vm.assertEqDecimal(left, right, decimals, err);
105 | | }
106 | |
107 | | function assertEq(address left, address right) internal pure virtual {
108 | | vm.assertEq(left, right);
109 | | }
110 | |
111 | | function assertEq(address left, address right, string memory err) internal pure virtual {
112 | | vm.assertEq(left, right, err);
113 | | }
114 | |
115 | | function assertEq(bytes32 left, bytes32 right) internal pure virtual {
116 | | vm.assertEq(left, right);
117 | | }
118 | |
119 | | function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
120 | | vm.assertEq(left, right, err);
121 | | }
122 | |
123 | | function assertEq32(bytes32 left, bytes32 right) internal pure virtual {
124 | | assertEq(left, right);
125 | | }
126 | |
127 | | function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
128 | | assertEq(left, right, err);
129 | | }
130 | |
131 | | function assertEq(string memory left, string memory right) internal pure virtual {
132 | | vm.assertEq(left, right);
133 | | }
134 | |
135 | | function assertEq(string memory left, string memory right, string memory err) internal pure virtual {
136 | | vm.assertEq(left, right, err);
137 | | }
138 | |
139 | | function assertEq(bytes memory left, bytes memory right) internal pure virtual {
140 | | vm.assertEq(left, right);
141 | | }
142 | |
143 | | function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
144 | | vm.assertEq(left, right, err);
145 | | }
146 | |
147 | | function assertEq(bool[] memory left, bool[] memory right) internal pure virtual {
148 | | vm.assertEq(left, right);
149 | | }
150 | |
151 | | function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
152 | | vm.assertEq(left, right, err);
153 | | }
154 | |
155 | | function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
156 | | vm.assertEq(left, right);
157 | | }
158 | |
159 | | function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
160 | | vm.assertEq(left, right, err);
161 | | }
162 | |
163 | | function assertEq(int256[] memory left, int256[] memory right) internal pure virtual {
164 | | vm.assertEq(left, right);
165 | | }
166 | |
167 | | function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
168 | | vm.assertEq(left, right, err);
169 | | }
170 | |
171 | | function assertEq(address[] memory left, address[] memory right) internal pure virtual {
172 | | vm.assertEq(left, right);
173 | | }
174 | |
175 | | function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
176 | | vm.assertEq(left, right, err);
177 | | }
178 | |
179 | | function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
180 | | vm.assertEq(left, right);
181 | | }
182 | |
183 | | function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
184 | | vm.assertEq(left, right, err);
185 | | }
186 | |
187 | | function assertEq(string[] memory left, string[] memory right) internal pure virtual {
188 | | vm.assertEq(left, right);
189 | | }
190 | |
191 | | function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
192 | | vm.assertEq(left, right, err);
193 | | }
194 | |
195 | | function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
196 | | vm.assertEq(left, right);
197 | | }
198 | |
199 | | function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
200 | | vm.assertEq(left, right, err);
201 | | }
202 | |
203 | | // Legacy helper
204 | | function assertEqUint(uint256 left, uint256 right) internal pure virtual {
205 | | assertEq(left, right);
206 | | }
207 | |
208 | | function assertNotEq(bool left, bool right) internal pure virtual {
209 | | vm.assertNotEq(left, right);
210 | | }
211 | |
212 | | function assertNotEq(bool left, bool right, string memory err) internal pure virtual {
213 | | vm.assertNotEq(left, right, err);
214 | | }
215 | |
216 | | function assertNotEq(uint256 left, uint256 right) internal pure virtual {
217 | | vm.assertNotEq(left, right);
218 | | }
219 | |
220 | | function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual {
221 | | vm.assertNotEq(left, right, err);
222 | | }
223 | |
224 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
225 | | vm.assertNotEqDecimal(left, right, decimals);
226 | | }
227 | |
228 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err)
229 | | internal
230 | | pure
231 | | virtual
232 | | {
233 | | vm.assertNotEqDecimal(left, right, decimals, err);
234 | | }
235 | |
236 | | function assertNotEq(int256 left, int256 right) internal pure virtual {
237 | | vm.assertNotEq(left, right);
238 | | }
239 | |
240 | | function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual {
241 | | vm.assertNotEq(left, right, err);
242 | | }
243 | |
244 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
245 | | vm.assertNotEqDecimal(left, right, decimals);
246 | | }
247 | |
248 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
249 | | vm.assertNotEqDecimal(left, right, decimals, err);
250 | | }
251 | |
252 | | function assertNotEq(address left, address right) internal pure virtual {
253 | | vm.assertNotEq(left, right);
254 | | }
255 | |
256 | | function assertNotEq(address left, address right, string memory err) internal pure virtual {
257 | | vm.assertNotEq(left, right, err);
258 | | }
259 | |
260 | | function assertNotEq(bytes32 left, bytes32 right) internal pure virtual {
261 | | vm.assertNotEq(left, right);
262 | | }
263 | |
264 | | function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
265 | | vm.assertNotEq(left, right, err);
266 | | }
267 | |
268 | | function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual {
269 | | assertNotEq(left, right);
270 | | }
271 | |
272 | | function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
273 | | assertNotEq(left, right, err);
274 | | }
275 | |
276 | | function assertNotEq(string memory left, string memory right) internal pure virtual {
277 | | vm.assertNotEq(left, right);
278 | | }
279 | |
280 | | function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual {
281 | | vm.assertNotEq(left, right, err);
282 | | }
283 | |
284 | | function assertNotEq(bytes memory left, bytes memory right) internal pure virtual {
285 | | vm.assertNotEq(left, right);
286 | | }
287 | |
288 | | function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
289 | | vm.assertNotEq(left, right, err);
290 | | }
291 | |
292 | | function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual {
293 | | vm.assertNotEq(left, right);
294 | | }
295 | |
296 | | function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
297 | | vm.assertNotEq(left, right, err);
298 | | }
299 | |
300 | | function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
301 | | vm.assertNotEq(left, right);
302 | | }
303 | |
304 | | function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
305 | | vm.assertNotEq(left, right, err);
306 | | }
307 | |
308 | | function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual {
309 | | vm.assertNotEq(left, right);
310 | | }
311 | |
312 | | function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
313 | | vm.assertNotEq(left, right, err);
314 | | }
315 | |
316 | | function assertNotEq(address[] memory left, address[] memory right) internal pure virtual {
317 | | vm.assertNotEq(left, right);
318 | | }
319 | |
320 | | function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
321 | | vm.assertNotEq(left, right, err);
322 | | }
323 | |
324 | | function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
325 | | vm.assertNotEq(left, right);
326 | | }
327 | |
328 | | function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
329 | | vm.assertNotEq(left, right, err);
330 | | }
331 | |
332 | | function assertNotEq(string[] memory left, string[] memory right) internal pure virtual {
333 | | vm.assertNotEq(left, right);
334 | | }
335 | |
336 | | function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
337 | | vm.assertNotEq(left, right, err);
338 | | }
339 | |
340 | | function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
341 | | vm.assertNotEq(left, right);
342 | | }
343 | |
344 | | function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
345 | | vm.assertNotEq(left, right, err);
346 | | }
347 | |
348 | | function assertLt(uint256 left, uint256 right) internal pure virtual {
349 | | vm.assertLt(left, right);
350 | | }
351 | |
352 | | function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual {
353 | | vm.assertLt(left, right, err);
354 | | }
355 | |
356 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
357 | | vm.assertLtDecimal(left, right, decimals);
358 | | }
359 | |
360 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
361 | | vm.assertLtDecimal(left, right, decimals, err);
362 | | }
363 | |
364 | | function assertLt(int256 left, int256 right) internal pure virtual {
365 | | vm.assertLt(left, right);
366 | | }
367 | |
368 | | function assertLt(int256 left, int256 right, string memory err) internal pure virtual {
369 | | vm.assertLt(left, right, err);
370 | | }
371 | |
372 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
373 | | vm.assertLtDecimal(left, right, decimals);
374 | | }
375 | |
376 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
377 | | vm.assertLtDecimal(left, right, decimals, err);
378 | | }
379 | |
380 | | function assertGt(uint256 left, uint256 right) internal pure virtual {
381 | | vm.assertGt(left, right);
382 | | }
383 | |
384 | | function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual {
385 | | vm.assertGt(left, right, err);
386 | | }
387 | |
388 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
389 | | vm.assertGtDecimal(left, right, decimals);
390 | | }
391 | |
392 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
393 | | vm.assertGtDecimal(left, right, decimals, err);
394 | | }
395 | |
396 | | function assertGt(int256 left, int256 right) internal pure virtual {
397 | | vm.assertGt(left, right);
398 | | }
399 | |
400 | | function assertGt(int256 left, int256 right, string memory err) internal pure virtual {
401 | | vm.assertGt(left, right, err);
402 | | }
403 | |
404 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
405 | | vm.assertGtDecimal(left, right, decimals);
406 | | }
407 | |
408 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
409 | | vm.assertGtDecimal(left, right, decimals, err);
410 | | }
411 | |
412 | | function assertLe(uint256 left, uint256 right) internal pure virtual {
413 | | vm.assertLe(left, right);
414 | | }
415 | |
416 | | function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual {
417 | | vm.assertLe(left, right, err);
418 | | }
419 | |
420 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
421 | | vm.assertLeDecimal(left, right, decimals);
422 | | }
423 | |
424 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
425 | | vm.assertLeDecimal(left, right, decimals, err);
426 | | }
427 | |
428 | | function assertLe(int256 left, int256 right) internal pure virtual {
429 | | vm.assertLe(left, right);
430 | | }
431 | |
432 | | function assertLe(int256 left, int256 right, string memory err) internal pure virtual {
433 | | vm.assertLe(left, right, err);
434 | | }
435 | |
436 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
437 | | vm.assertLeDecimal(left, right, decimals);
438 | | }
439 | |
440 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
441 | | vm.assertLeDecimal(left, right, decimals, err);
442 | | }
443 | |
444 | | function assertGe(uint256 left, uint256 right) internal pure virtual {
445 | | vm.assertGe(left, right);
446 | | }
447 | |
448 | | function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual {
449 | | vm.assertGe(left, right, err);
450 | | }
451 | |
452 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
453 | | vm.assertGeDecimal(left, right, decimals);
454 | | }
455 | |
456 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
457 | | vm.assertGeDecimal(left, right, decimals, err);
458 | | }
459 | |
460 | | function assertGe(int256 left, int256 right) internal pure virtual {
461 | | vm.assertGe(left, right);
462 | | }
463 | |
464 | | function assertGe(int256 left, int256 right, string memory err) internal pure virtual {
465 | | vm.assertGe(left, right, err);
466 | | }
467 | |
468 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
469 | | vm.assertGeDecimal(left, right, decimals);
470 | | }
471 | |
472 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
473 | | vm.assertGeDecimal(left, right, decimals, err);
474 | | }
475 | |
476 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual {
477 | | vm.assertApproxEqAbs(left, right, maxDelta);
478 | | }
479 | |
480 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err)
481 | | internal
482 | | pure
483 | | virtual
484 | | {
485 | | vm.assertApproxEqAbs(left, right, maxDelta, err);
486 | | }
487 | |
488 | | function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals)
489 | | internal
490 | | pure
491 | | virtual
492 | | {
493 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
494 | | }
495 | |
496 | | function assertApproxEqAbsDecimal(
497 | | uint256 left,
498 | | uint256 right,
499 | | uint256 maxDelta,
500 | | uint256 decimals,
501 | | string memory err
502 | | ) internal pure virtual {
503 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
504 | | }
505 | |
506 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual {
507 | | vm.assertApproxEqAbs(left, right, maxDelta);
508 | | }
509 | |
510 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual {
511 | | vm.assertApproxEqAbs(left, right, maxDelta, err);
512 | | }
513 | |
514 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals)
515 | | internal
516 | | pure
517 | | virtual
518 | | {
519 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
520 | | }
521 | |
522 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err)
523 | | internal
524 | | pure
525 | | virtual
526 | | {
527 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
528 | | }
529 | |
530 | | function assertApproxEqRel(
531 | | uint256 left,
532 | | uint256 right,
533 | | uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
534 | | ) internal pure virtual {
535 | | vm.assertApproxEqRel(left, right, maxPercentDelta);
536 | | }
537 | |
538 | | function assertApproxEqRel(
539 | | uint256 left,
540 | | uint256 right,
541 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
542 | | string memory err
543 | | ) internal pure virtual {
544 | | vm.assertApproxEqRel(left, right, maxPercentDelta, err);
545 | | }
546 | |
547 | | function assertApproxEqRelDecimal(
548 | | uint256 left,
549 | | uint256 right,
550 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
551 | | uint256 decimals
552 | | ) internal pure virtual {
553 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
554 | | }
555 | |
556 | | function assertApproxEqRelDecimal(
557 | | uint256 left,
558 | | uint256 right,
559 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
560 | | uint256 decimals,
561 | | string memory err
562 | | ) internal pure virtual {
563 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
564 | | }
565 | |
566 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual {
567 | | vm.assertApproxEqRel(left, right, maxPercentDelta);
568 | | }
569 | |
570 | | function assertApproxEqRel(
571 | | int256 left,
572 | | int256 right,
573 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
574 | | string memory err
575 | | ) internal pure virtual {
576 | | vm.assertApproxEqRel(left, right, maxPercentDelta, err);
577 | | }
578 | |
579 | | function assertApproxEqRelDecimal(
580 | | int256 left,
581 | | int256 right,
582 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
583 | | uint256 decimals
584 | | ) internal pure virtual {
585 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
586 | | }
587 | |
588 | | function assertApproxEqRelDecimal(
589 | | int256 left,
590 | | int256 right,
591 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
592 | | uint256 decimals,
593 | | string memory err
594 | | ) internal pure virtual {
595 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
596 | | }
597 | |
598 | | // Inherited from DSTest, not used but kept for backwards-compatibility
599 | | function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) {
600 | | return keccak256(left) == keccak256(right);
601 | | }
602 | |
603 | | function assertEq0(bytes memory left, bytes memory right) internal pure virtual {
604 | | assertEq(left, right);
605 | | }
606 | |
607 | | function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
608 | | assertEq(left, right, err);
609 | | }
610 | |
611 | | function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual {
612 | | assertNotEq(left, right);
613 | | }
614 | |
615 | | function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
616 | | assertNotEq(left, right, err);
617 | | }
618 | |
619 | | function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {
620 | | assertEqCall(target, callDataA, target, callDataB, true);
621 | | }
622 | |
623 | | function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)
624 | | internal
625 | | virtual
626 | | {
627 | | assertEqCall(targetA, callDataA, targetB, callDataB, true);
628 | | }
629 | |
630 | | function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)
631 | | internal
632 | | virtual
633 | | {
634 | | assertEqCall(target, callDataA, target, callDataB, strictRevertData);
635 | | }
636 | |
637 | | function assertEqCall(
638 | | address targetA,
639 | | bytes memory callDataA,
640 | | address targetB,
641 | | bytes memory callDataB,
642 | | bool strictRevertData
643 | | ) internal virtual {
644 | | (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);
645 | | (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);
646 | |
647 | | if (successA && successB) {
648 | | assertEq(returnDataA, returnDataB, "Call return data does not match");
649 | | }
650 | |
651 | | if (!successA && !successB && strictRevertData) {
652 | | assertEq(returnDataA, returnDataB, "Call revert data does not match");
653 | | }
654 | |
655 | | if (!successA && successB) {
656 | | emit log("Error: Calls were not equal");
657 | | emit log_named_bytes(" Left call revert data", returnDataA);
658 | | emit log_named_bytes(" Right call return data", returnDataB);
659 | | revert("assertion failed");
660 | | }
661 | |
662 | | if (successA && !successB) {
663 | | emit log("Error: Calls were not equal");
664 | | emit log_named_bytes(" Left call return data", returnDataA);
665 | | emit log_named_bytes(" Right call revert data", returnDataB);
666 | | revert("assertion failed");
667 | | }
668 | | }
669 | | }
670 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdChains.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | import {VmSafe} from "./Vm.sol";
5 | |
6 | | /**
7 | | * StdChains provides information about EVM compatible chains that can be used in scripts/tests.
8 | | * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
9 | | * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
10 | | * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
11 | | * alias used in this contract, which can be found as the first argument to the
12 | | * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
13 | | *
14 | | * There are two main ways to use this contract:
15 | | * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
16 | | * `setChain(string memory chainAlias, Chain memory chain)`
17 | | * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
18 | | *
19 | | * The first time either of those are used, chains are initialized with the default set of RPC URLs.
20 | | * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
21 | | * `defaultRpcUrls`.
22 | | *
23 | | * The `setChain` function is straightforward, and it simply saves off the given chain data.
24 | | *
25 | | * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
26 | | * we want to retrieve the RPC URL for `mainnet`:
27 | | * - If you have specified data with `setChain`, it will return that.
28 | | * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
29 | | * is valid (e.g. a URL is specified, or an environment variable is given and exists).
30 | | * - If neither of the above conditions is met, the default data is returned.
31 | | *
32 | | * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
33 | | */
34 | | abstract contract StdChains {
35 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
36 | |
37 | | bool private stdChainsInitialized;
38 | |
39 | | struct ChainData {
40 | | string name;
41 | | uint256 chainId;
42 | | string rpcUrl;
43 | | }
44 | |
45 | | struct Chain {
46 | | // The chain name.
47 | | string name;
48 | | // The chain's Chain ID.
49 | | uint256 chainId;
50 | | // The chain's alias. (i.e. what gets specified in `foundry.toml`).
51 | | string chainAlias;
52 | | // A default RPC endpoint for this chain.
53 | | // NOTE: This default RPC URL is included for convenience to facilitate quick tests and
54 | | // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
55 | | // usage as you will be throttled and this is a disservice to others who need this endpoint.
56 | | string rpcUrl;
57 | | }
58 | |
59 | | // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
60 | | mapping(string => Chain) private chains;
61 | | // Maps from the chain's alias to it's default RPC URL.
62 | | mapping(string => string) private defaultRpcUrls;
63 | | // Maps from a chain ID to it's alias.
64 | | mapping(uint256 => string) private idToAlias;
65 | |
66 | | bool private fallbackToDefaultRpcUrls = true;
67 | |
68 | | // The RPC URL will be fetched from config or defaultRpcUrls if possible.
69 | | function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
70 | | require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
71 | |
72 | | initializeStdChains();
73 | | chain = chains[chainAlias];
74 | | require(
75 | | chain.chainId != 0,
76 | | string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
77 | | );
78 | |
79 | | chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
80 | | }
81 | |
82 | | function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
83 | | require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
84 | | initializeStdChains();
85 | | string memory chainAlias = idToAlias[chainId];
86 | |
87 | | chain = chains[chainAlias];
88 | |
89 | | require(
90 | | chain.chainId != 0,
91 | | string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
92 | | );
93 | |
94 | | chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
95 | | }
96 | |
97 | | // set chain info, with priority to argument's rpcUrl field.
98 | | function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
99 | | require(
100 | | bytes(chainAlias).length != 0,
101 | | "StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
102 | | );
103 | |
104 | | require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
105 | |
106 | | initializeStdChains();
107 | | string memory foundAlias = idToAlias[chain.chainId];
108 | |
109 | | require(
110 | | bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
111 | | string(
112 | | abi.encodePacked(
113 | | "StdChains setChain(string,ChainData): Chain ID ",
114 | | vm.toString(chain.chainId),
115 | | " already used by \"",
116 | | foundAlias,
117 | | "\"."
118 | | )
119 | | )
120 | | );
121 | |
122 | | uint256 oldChainId = chains[chainAlias].chainId;
123 | | delete idToAlias[oldChainId];
124 | |
125 | | chains[chainAlias] =
126 | | Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
127 | | idToAlias[chain.chainId] = chainAlias;
128 | | }
129 | |
130 | | // set chain info, with priority to argument's rpcUrl field.
131 | | function setChain(string memory chainAlias, Chain memory chain) internal virtual {
132 | | setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
133 | | }
134 | |
135 | | function _toUpper(string memory str) private pure returns (string memory) {
136 | | bytes memory strb = bytes(str);
137 | | bytes memory copy = new bytes(strb.length);
138 | | for (uint256 i = 0; i < strb.length; i++) {
139 | | bytes1 b = strb[i];
140 | | if (b >= 0x61 && b <= 0x7A) {
141 | | copy[i] = bytes1(uint8(b) - 32);
142 | | } else {
143 | | copy[i] = b;
144 | | }
145 | | }
146 | | return string(copy);
147 | | }
148 | |
149 | | // lookup rpcUrl, in descending order of priority:
150 | | // current -> config (foundry.toml) -> environment variable -> default
151 | | function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
152 | | private
153 | | view
154 | | returns (Chain memory)
155 | | {
156 | | if (bytes(chain.rpcUrl).length == 0) {
157 | | try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
158 | | chain.rpcUrl = configRpcUrl;
159 | | } catch (bytes memory err) {
160 | | string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
161 | | if (fallbackToDefaultRpcUrls) {
162 | | chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
163 | | } else {
164 | | chain.rpcUrl = vm.envString(envName);
165 | | }
166 | | // Distinguish 'not found' from 'cannot read'
167 | | // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
168 | | bytes memory oldNotFoundError =
169 | | abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
170 | | bytes memory newNotFoundError = abi.encodeWithSignature(
171 | | "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
172 | | );
173 | | bytes32 errHash = keccak256(err);
174 | | if (
175 | | (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
176 | | || bytes(chain.rpcUrl).length == 0
177 | | ) {
178 | | /// @solidity memory-safe-assembly
179 | | assembly {
180 | | revert(add(32, err), mload(err))
181 | | }
182 | | }
183 | | }
184 | | }
185 | | return chain;
186 | | }
187 | |
188 | | function setFallbackToDefaultRpcUrls(bool useDefault) internal {
189 | | fallbackToDefaultRpcUrls = useDefault;
190 | | }
191 | |
192 | | function initializeStdChains() private {
193 | | if (stdChainsInitialized) return;
194 | |
195 | | stdChainsInitialized = true;
196 | |
197 | | // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol`
198 | | setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
199 | | setChainWithDefaultRpcUrl(
200 | | "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP")
201 | | );
202 | | setChainWithDefaultRpcUrl(
203 | | "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
204 | | );
205 | | setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
206 | | setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
207 | | setChainWithDefaultRpcUrl(
208 | | "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
209 | | );
210 | | setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
211 | | setChainWithDefaultRpcUrl(
212 | | "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
213 | | );
214 | | setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
215 | | setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
216 | | setChainWithDefaultRpcUrl(
217 | | "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
218 | | );
219 | | setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
220 | | setChainWithDefaultRpcUrl(
221 | | "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
222 | | );
223 | | setChainWithDefaultRpcUrl(
224 | | "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
225 | | );
226 | | setChainWithDefaultRpcUrl(
227 | | "bnb_smart_chain_testnet",
228 | | ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
229 | | );
230 | | setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
231 | | setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
232 | | setChainWithDefaultRpcUrl(
233 | | "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
234 | | );
235 | | setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
236 | | setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
237 | | setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
238 | | setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
239 | | setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
240 | | setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
241 | | setChainWithDefaultRpcUrl(
242 | | "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
243 | | );
244 | | setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
245 | | setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
246 | | setChainWithDefaultRpcUrl(
247 | | "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
248 | | );
249 | | setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc"));
250 | | setChainWithDefaultRpcUrl(
251 | | "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc")
252 | | );
253 | | }
254 | |
255 | | // set chain info, with priority to chainAlias' rpc url in foundry.toml
256 | | function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
257 | | string memory rpcUrl = chain.rpcUrl;
258 | | defaultRpcUrls[chainAlias] = rpcUrl;
259 | | chain.rpcUrl = "";
260 | | setChain(chainAlias, chain);
261 | | chain.rpcUrl = rpcUrl; // restore argument
262 | | }
263 | | }
264 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdCheats.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | import {StdStorage, stdStorage} from "./StdStorage.sol";
7 | | import {console2} from "./console2.sol";
8 | | import {Vm} from "./Vm.sol";
9 | |
10 | | abstract contract StdCheatsSafe {
11 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
12 | |
13 | | uint256 private constant UINT256_MAX =
14 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935;
15 | |
16 | | bool private gasMeteringOff;
17 | |
18 | | // Data structures to parse Transaction objects from the broadcast artifact
19 | | // that conform to EIP1559. The Raw structs is what is parsed from the JSON
20 | | // and then converted to the one that is used by the user for better UX.
21 | |
22 | | struct RawTx1559 {
23 | | string[] arguments;
24 | | address contractAddress;
25 | | string contractName;
26 | | // json value name = function
27 | | string functionSig;
28 | | bytes32 hash;
29 | | // json value name = tx
30 | | RawTx1559Detail txDetail;
31 | | // json value name = type
32 | | string opcode;
33 | | }
34 | |
35 | | struct RawTx1559Detail {
36 | | AccessList[] accessList;
37 | | bytes data;
38 | | address from;
39 | | bytes gas;
40 | | bytes nonce;
41 | | address to;
42 | | bytes txType;
43 | | bytes value;
44 | | }
45 | |
46 | | struct Tx1559 {
47 | | string[] arguments;
48 | | address contractAddress;
49 | | string contractName;
50 | | string functionSig;
51 | | bytes32 hash;
52 | | Tx1559Detail txDetail;
53 | | string opcode;
54 | | }
55 | |
56 | | struct Tx1559Detail {
57 | | AccessList[] accessList;
58 | | bytes data;
59 | | address from;
60 | | uint256 gas;
61 | | uint256 nonce;
62 | | address to;
63 | | uint256 txType;
64 | | uint256 value;
65 | | }
66 | |
67 | | // Data structures to parse Transaction objects from the broadcast artifact
68 | | // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
69 | | // and then converted to the one that is used by the user for better UX.
70 | |
71 | | struct TxLegacy {
72 | | string[] arguments;
73 | | address contractAddress;
74 | | string contractName;
75 | | string functionSig;
76 | | string hash;
77 | | string opcode;
78 | | TxDetailLegacy transaction;
79 | | }
80 | |
81 | | struct TxDetailLegacy {
82 | | AccessList[] accessList;
83 | | uint256 chainId;
84 | | bytes data;
85 | | address from;
86 | | uint256 gas;
87 | | uint256 gasPrice;
88 | | bytes32 hash;
89 | | uint256 nonce;
90 | | bytes1 opcode;
91 | | bytes32 r;
92 | | bytes32 s;
93 | | uint256 txType;
94 | | address to;
95 | | uint8 v;
96 | | uint256 value;
97 | | }
98 | |
99 | | struct AccessList {
100 | | address accessAddress;
101 | | bytes32[] storageKeys;
102 | | }
103 | |
104 | | // Data structures to parse Receipt objects from the broadcast artifact.
105 | | // The Raw structs is what is parsed from the JSON
106 | | // and then converted to the one that is used by the user for better UX.
107 | |
108 | | struct RawReceipt {
109 | | bytes32 blockHash;
110 | | bytes blockNumber;
111 | | address contractAddress;
112 | | bytes cumulativeGasUsed;
113 | | bytes effectiveGasPrice;
114 | | address from;
115 | | bytes gasUsed;
116 | | RawReceiptLog[] logs;
117 | | bytes logsBloom;
118 | | bytes status;
119 | | address to;
120 | | bytes32 transactionHash;
121 | | bytes transactionIndex;
122 | | }
123 | |
124 | | struct Receipt {
125 | | bytes32 blockHash;
126 | | uint256 blockNumber;
127 | | address contractAddress;
128 | | uint256 cumulativeGasUsed;
129 | | uint256 effectiveGasPrice;
130 | | address from;
131 | | uint256 gasUsed;
132 | | ReceiptLog[] logs;
133 | | bytes logsBloom;
134 | | uint256 status;
135 | | address to;
136 | | bytes32 transactionHash;
137 | | uint256 transactionIndex;
138 | | }
139 | |
140 | | // Data structures to parse the entire broadcast artifact, assuming the
141 | | // transactions conform to EIP1559.
142 | |
143 | | struct EIP1559ScriptArtifact {
144 | | string[] libraries;
145 | | string path;
146 | | string[] pending;
147 | | Receipt[] receipts;
148 | | uint256 timestamp;
149 | | Tx1559[] transactions;
150 | | TxReturn[] txReturns;
151 | | }
152 | |
153 | | struct RawEIP1559ScriptArtifact {
154 | | string[] libraries;
155 | | string path;
156 | | string[] pending;
157 | | RawReceipt[] receipts;
158 | | TxReturn[] txReturns;
159 | | uint256 timestamp;
160 | | RawTx1559[] transactions;
161 | | }
162 | |
163 | | struct RawReceiptLog {
164 | | // json value = address
165 | | address logAddress;
166 | | bytes32 blockHash;
167 | | bytes blockNumber;
168 | | bytes data;
169 | | bytes logIndex;
170 | | bool removed;
171 | | bytes32[] topics;
172 | | bytes32 transactionHash;
173 | | bytes transactionIndex;
174 | | bytes transactionLogIndex;
175 | | }
176 | |
177 | | struct ReceiptLog {
178 | | // json value = address
179 | | address logAddress;
180 | | bytes32 blockHash;
181 | | uint256 blockNumber;
182 | | bytes data;
183 | | uint256 logIndex;
184 | | bytes32[] topics;
185 | | uint256 transactionIndex;
186 | | uint256 transactionLogIndex;
187 | | bool removed;
188 | | }
189 | |
190 | | struct TxReturn {
191 | | string internalType;
192 | | string value;
193 | | }
194 | |
195 | | struct Account {
196 | | address addr;
197 | | uint256 key;
198 | | }
199 | |
200 | | enum AddressType {
201 | | Payable,
202 | | NonPayable,
203 | | ZeroAddress,
204 | | Precompile,
205 | | ForgeAddress
206 | | }
207 | |
208 | | // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
209 | | function assumeNotBlacklisted(address token, address addr) internal view virtual {
210 | | // Nothing to check if `token` is not a contract.
211 | | uint256 tokenCodeSize;
212 | | assembly {
213 | | tokenCodeSize := extcodesize(token)
214 | | }
215 | | require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
216 | |
217 | | bool success;
218 | | bytes memory returnData;
219 | |
220 | | // 4-byte selector for `isBlacklisted(address)`, used by USDC.
221 | | (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
222 | | vm.assume(!success || abi.decode(returnData, (bool)) == false);
223 | |
224 | | // 4-byte selector for `isBlackListed(address)`, used by USDT.
225 | | (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
226 | | vm.assume(!success || abi.decode(returnData, (bool)) == false);
227 | | }
228 | |
229 | | // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
230 | | // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
231 | | // backwards compatibility, since this name was used in the original PR which already has
232 | | // a release. This function can be removed in a future release once we want a breaking change.
233 | | function assumeNoBlacklisted(address token, address addr) internal view virtual {
234 | | assumeNotBlacklisted(token, addr);
235 | | }
236 | |
237 | | function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
238 | | if (addressType == AddressType.Payable) {
239 | | assumeNotPayable(addr);
240 | | } else if (addressType == AddressType.NonPayable) {
241 | | assumePayable(addr);
242 | | } else if (addressType == AddressType.ZeroAddress) {
243 | | assumeNotZeroAddress(addr);
244 | | } else if (addressType == AddressType.Precompile) {
245 | | assumeNotPrecompile(addr);
246 | | } else if (addressType == AddressType.ForgeAddress) {
247 | | assumeNotForgeAddress(addr);
248 | | }
249 | | }
250 | |
251 | | function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
252 | | assumeAddressIsNot(addr, addressType1);
253 | | assumeAddressIsNot(addr, addressType2);
254 | | }
255 | |
256 | | function assumeAddressIsNot(
257 | | address addr,
258 | | AddressType addressType1,
259 | | AddressType addressType2,
260 | | AddressType addressType3
261 | | ) internal virtual {
262 | | assumeAddressIsNot(addr, addressType1);
263 | | assumeAddressIsNot(addr, addressType2);
264 | | assumeAddressIsNot(addr, addressType3);
265 | | }
266 | |
267 | | function assumeAddressIsNot(
268 | | address addr,
269 | | AddressType addressType1,
270 | | AddressType addressType2,
271 | | AddressType addressType3,
272 | | AddressType addressType4
273 | | ) internal virtual {
274 | | assumeAddressIsNot(addr, addressType1);
275 | | assumeAddressIsNot(addr, addressType2);
276 | | assumeAddressIsNot(addr, addressType3);
277 | | assumeAddressIsNot(addr, addressType4);
278 | | }
279 | |
280 | | // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
281 | | // `addr` and checking the `success` return value.
282 | | // NOTE: This function may result in state changes depending on the fallback/receive logic
283 | | // implemented by `addr`, which should be taken into account when this function is used.
284 | | function _isPayable(address addr) private returns (bool) {
285 | | require(
286 | | addr.balance < UINT256_MAX,
287 | | "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
288 | | );
289 | | uint256 origBalanceTest = address(this).balance;
290 | | uint256 origBalanceAddr = address(addr).balance;
291 | |
292 | | vm.deal(address(this), 1);
293 | | (bool success,) = payable(addr).call{value: 1}("");
294 | |
295 | | // reset balances
296 | | vm.deal(address(this), origBalanceTest);
297 | | vm.deal(addr, origBalanceAddr);
298 | |
299 | | return success;
300 | | }
301 | |
302 | | // NOTE: This function may result in state changes depending on the fallback/receive logic
303 | | // implemented by `addr`, which should be taken into account when this function is used. See the
304 | | // `_isPayable` method for more information.
305 | | function assumePayable(address addr) internal virtual {
306 | | vm.assume(_isPayable(addr));
307 | | }
308 | |
309 | | function assumeNotPayable(address addr) internal virtual {
310 | | vm.assume(!_isPayable(addr));
311 | | }
312 | |
313 | | function assumeNotZeroAddress(address addr) internal pure virtual {
314 | | vm.assume(addr != address(0));
315 | | }
316 | |
317 | | function assumeNotPrecompile(address addr) internal pure virtual {
318 | | assumeNotPrecompile(addr, _pureChainId());
319 | | }
320 | |
321 | | function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
322 | | // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
323 | | // address), but the same rationale for excluding them applies so we include those too.
324 | |
325 | | // These are reserved by Ethereum and may be on all EVM-compatible chains.
326 | | vm.assume(addr < address(0x1) || addr > address(0xff));
327 | |
328 | | // forgefmt: disable-start
329 | | if (chainId == 10 || chainId == 420) {
330 | | // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
331 | | vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
332 | | } else if (chainId == 42161 || chainId == 421613) {
333 | | // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
334 | | vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
335 | | } else if (chainId == 43114 || chainId == 43113) {
336 | | // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
337 | | vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
338 | | vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
339 | | vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
340 | | }
341 | | // forgefmt: disable-end
342 | | }
343 | |
344 | | function assumeNotForgeAddress(address addr) internal pure virtual {
345 | | // vm, console, and Create2Deployer addresses
346 | | vm.assume(
347 | | addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
348 | | && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
349 | | );
350 | | }
351 | |
352 | | function readEIP1559ScriptArtifact(string memory path)
353 | | internal
354 | | view
355 | | virtual
356 | | returns (EIP1559ScriptArtifact memory)
357 | | {
358 | | string memory data = vm.readFile(path);
359 | | bytes memory parsedData = vm.parseJson(data);
360 | | RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
361 | | EIP1559ScriptArtifact memory artifact;
362 | | artifact.libraries = rawArtifact.libraries;
363 | | artifact.path = rawArtifact.path;
364 | | artifact.timestamp = rawArtifact.timestamp;
365 | | artifact.pending = rawArtifact.pending;
366 | | artifact.txReturns = rawArtifact.txReturns;
367 | | artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
368 | | artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
369 | | return artifact;
370 | | }
371 | |
372 | | function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
373 | | Tx1559[] memory txs = new Tx1559[](rawTxs.length);
374 | | for (uint256 i; i < rawTxs.length; i++) {
375 | | txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
376 | | }
377 | | return txs;
378 | | }
379 | |
380 | | function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
381 | | Tx1559 memory transaction;
382 | | transaction.arguments = rawTx.arguments;
383 | | transaction.contractName = rawTx.contractName;
384 | | transaction.functionSig = rawTx.functionSig;
385 | | transaction.hash = rawTx.hash;
386 | | transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
387 | | transaction.opcode = rawTx.opcode;
388 | | return transaction;
389 | | }
390 | |
391 | | function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
392 | | internal
393 | | pure
394 | | virtual
395 | | returns (Tx1559Detail memory)
396 | | {
397 | | Tx1559Detail memory txDetail;
398 | | txDetail.data = rawDetail.data;
399 | | txDetail.from = rawDetail.from;
400 | | txDetail.to = rawDetail.to;
401 | | txDetail.nonce = _bytesToUint(rawDetail.nonce);
402 | | txDetail.txType = _bytesToUint(rawDetail.txType);
403 | | txDetail.value = _bytesToUint(rawDetail.value);
404 | | txDetail.gas = _bytesToUint(rawDetail.gas);
405 | | txDetail.accessList = rawDetail.accessList;
406 | | return txDetail;
407 | | }
408 | |
409 | | function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
410 | | string memory deployData = vm.readFile(path);
411 | | bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
412 | | RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
413 | | return rawToConvertedEIPTx1559s(rawTxs);
414 | | }
415 | |
416 | | function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
417 | | string memory deployData = vm.readFile(path);
418 | | string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
419 | | bytes memory parsedDeployData = vm.parseJson(deployData, key);
420 | | RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
421 | | return rawToConvertedEIPTx1559(rawTx);
422 | | }
423 | |
424 | | // Analogous to readTransactions, but for receipts.
425 | | function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
426 | | string memory deployData = vm.readFile(path);
427 | | bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
428 | | RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
429 | | return rawToConvertedReceipts(rawReceipts);
430 | | }
431 | |
432 | | function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
433 | | string memory deployData = vm.readFile(path);
434 | | string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
435 | | bytes memory parsedDeployData = vm.parseJson(deployData, key);
436 | | RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
437 | | return rawToConvertedReceipt(rawReceipt);
438 | | }
439 | |
440 | | function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
441 | | Receipt[] memory receipts = new Receipt[](rawReceipts.length);
442 | | for (uint256 i; i < rawReceipts.length; i++) {
443 | | receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
444 | | }
445 | | return receipts;
446 | | }
447 | |
448 | | function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
449 | | Receipt memory receipt;
450 | | receipt.blockHash = rawReceipt.blockHash;
451 | | receipt.to = rawReceipt.to;
452 | | receipt.from = rawReceipt.from;
453 | | receipt.contractAddress = rawReceipt.contractAddress;
454 | | receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
455 | | receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
456 | | receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
457 | | receipt.status = _bytesToUint(rawReceipt.status);
458 | | receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
459 | | receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
460 | | receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
461 | | receipt.logsBloom = rawReceipt.logsBloom;
462 | | receipt.transactionHash = rawReceipt.transactionHash;
463 | | return receipt;
464 | | }
465 | |
466 | | function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
467 | | internal
468 | | pure
469 | | virtual
470 | | returns (ReceiptLog[] memory)
471 | | {
472 | | ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
473 | | for (uint256 i; i < rawLogs.length; i++) {
474 | | logs[i].logAddress = rawLogs[i].logAddress;
475 | | logs[i].blockHash = rawLogs[i].blockHash;
476 | | logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
477 | | logs[i].data = rawLogs[i].data;
478 | | logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
479 | | logs[i].topics = rawLogs[i].topics;
480 | | logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
481 | | logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
482 | | logs[i].removed = rawLogs[i].removed;
483 | | }
484 | | return logs;
485 | | }
486 | |
487 | | // Deploy a contract by fetching the contract bytecode from
488 | | // the artifacts directory
489 | | // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
490 | | function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
491 | | bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
492 | | /// @solidity memory-safe-assembly
493 | | assembly {
494 | | addr := create(0, add(bytecode, 0x20), mload(bytecode))
495 | | }
496 | |
497 | | require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
498 | | }
499 | |
500 | | function deployCode(string memory what) internal virtual returns (address addr) {
501 | | bytes memory bytecode = vm.getCode(what);
502 | | /// @solidity memory-safe-assembly
503 | | assembly {
504 | | addr := create(0, add(bytecode, 0x20), mload(bytecode))
505 | | }
506 | |
507 | | require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
508 | | }
509 | |
510 | | /// @dev deploy contract with value on construction
511 | | function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
512 | | bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
513 | | /// @solidity memory-safe-assembly
514 | | assembly {
515 | | addr := create(val, add(bytecode, 0x20), mload(bytecode))
516 | | }
517 | |
518 | | require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
519 | | }
520 | |
521 | | function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
522 | | bytes memory bytecode = vm.getCode(what);
523 | | /// @solidity memory-safe-assembly
524 | | assembly {
525 | | addr := create(val, add(bytecode, 0x20), mload(bytecode))
526 | | }
527 | |
528 | | require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
529 | | }
530 | |
531 | | // creates a labeled address and the corresponding private key
532 | | function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
533 | | privateKey = uint256(keccak256(abi.encodePacked(name)));
534 | | addr = vm.addr(privateKey);
535 | | vm.label(addr, name);
536 | | }
537 | |
538 | | // creates a labeled address
539 | | function makeAddr(string memory name) internal virtual returns (address addr) {
540 | | (addr,) = makeAddrAndKey(name);
541 | | }
542 | |
543 | | // Destroys an account immediately, sending the balance to beneficiary.
544 | | // Destroying means: balance will be zero, code will be empty, and nonce will be 0
545 | | // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
546 | | // only after tx ends, this will run immediately.
547 | | function destroyAccount(address who, address beneficiary) internal virtual {
548 | | uint256 currBalance = who.balance;
549 | | vm.etch(who, abi.encode());
550 | | vm.deal(who, 0);
551 | | vm.resetNonce(who);
552 | |
553 | | uint256 beneficiaryBalance = beneficiary.balance;
554 | | vm.deal(beneficiary, currBalance + beneficiaryBalance);
555 | | }
556 | |
557 | | // creates a struct containing both a labeled address and the corresponding private key
558 | | function makeAccount(string memory name) internal virtual returns (Account memory account) {
559 | | (account.addr, account.key) = makeAddrAndKey(name);
560 | | }
561 | |
562 | | function deriveRememberKey(string memory mnemonic, uint32 index)
563 | | internal
564 | | virtual
565 | | returns (address who, uint256 privateKey)
566 | | {
567 | | privateKey = vm.deriveKey(mnemonic, index);
568 | | who = vm.rememberKey(privateKey);
569 | | }
570 | |
571 | | function _bytesToUint(bytes memory b) private pure returns (uint256) {
572 | | require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
573 | | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
574 | | }
575 | |
576 | | function isFork() internal view virtual returns (bool status) {
577 | | try vm.activeFork() {
578 | | status = true;
579 | | } catch (bytes memory) {}
580 | | }
581 | |
582 | | modifier skipWhenForking() {
583 | | if (!isFork()) {
584 | | _;
585 | | }
586 | | }
587 | |
588 | | modifier skipWhenNotForking() {
589 | | if (isFork()) {
590 | | _;
591 | | }
592 | | }
593 | |
594 | | modifier noGasMetering() {
595 | | vm.pauseGasMetering();
596 | | // To prevent turning gas monitoring back on with nested functions that use this modifier,
597 | | // we check if gasMetering started in the off position. If it did, we don't want to turn
598 | | // it back on until we exit the top level function that used the modifier
599 | | //
600 | | // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
601 | | // funcA will have `gasStartedOff` as false, funcB will have it as true,
602 | | // so we only turn metering back on at the end of the funcA
603 | | bool gasStartedOff = gasMeteringOff;
604 | | gasMeteringOff = true;
605 | |
606 | | _;
607 | |
608 | | // if gas metering was on when this modifier was called, turn it back on at the end
609 | | if (!gasStartedOff) {
610 | | gasMeteringOff = false;
611 | | vm.resumeGasMetering();
612 | | }
613 | | }
614 | |
615 | | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
616 | | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
617 | | // can't simply access the chain ID in a normal view or pure function because the solc View Pure
618 | | // Checker changed `chainid` from pure to view in 0.8.0.
619 | | function _viewChainId() private view returns (uint256 chainId) {
620 | | // Assembly required since `block.chainid` was introduced in 0.8.0.
621 | | assembly {
622 | | chainId := chainid()
623 | | }
624 | |
625 | | address(this); // Silence warnings in older Solc versions.
626 | | }
627 | |
628 | | function _pureChainId() private pure returns (uint256 chainId) {
629 | | function() internal view returns (uint256) fnIn = _viewChainId;
630 | | function() internal pure returns (uint256) pureChainId;
631 | | assembly {
632 | | pureChainId := fnIn
633 | | }
634 | | chainId = pureChainId();
635 | | }
636 | | }
637 | |
638 | | // Wrappers around cheatcodes to avoid footguns
639 | | abstract contract StdCheats is StdCheatsSafe {
640 | | using stdStorage for StdStorage;
641 | |
642 | | StdStorage private stdstore;
643 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
644 | | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
645 | |
646 | | // Skip forward or rewind time by the specified number of seconds
647 | | function skip(uint256 time) internal virtual {
648 | | vm.warp(block.timestamp + time);
649 | | }
650 | |
651 | | function rewind(uint256 time) internal virtual {
652 | | vm.warp(block.timestamp - time);
653 | | }
654 | |
655 | | // Setup a prank from an address that has some ether
656 | | function hoax(address msgSender) internal virtual {
657 | | vm.deal(msgSender, 1 << 128);
658 | | vm.prank(msgSender);
659 | | }
660 | |
661 | | function hoax(address msgSender, uint256 give) internal virtual {
662 | | vm.deal(msgSender, give);
663 | | vm.prank(msgSender);
664 | | }
665 | |
666 | | function hoax(address msgSender, address origin) internal virtual {
667 | | vm.deal(msgSender, 1 << 128);
668 | | vm.prank(msgSender, origin);
669 | | }
670 | |
671 | | function hoax(address msgSender, address origin, uint256 give) internal virtual {
672 | | vm.deal(msgSender, give);
673 | | vm.prank(msgSender, origin);
674 | | }
675 | |
676 | | // Start perpetual prank from an address that has some ether
677 | | function startHoax(address msgSender) internal virtual {
678 | | vm.deal(msgSender, 1 << 128);
679 | | vm.startPrank(msgSender);
680 | | }
681 | |
682 | | function startHoax(address msgSender, uint256 give) internal virtual {
683 | | vm.deal(msgSender, give);
684 | | vm.startPrank(msgSender);
685 | | }
686 | |
687 | | // Start perpetual prank from an address that has some ether
688 | | // tx.origin is set to the origin parameter
689 | | function startHoax(address msgSender, address origin) internal virtual {
690 | | vm.deal(msgSender, 1 << 128);
691 | | vm.startPrank(msgSender, origin);
692 | | }
693 | |
694 | | function startHoax(address msgSender, address origin, uint256 give) internal virtual {
695 | | vm.deal(msgSender, give);
696 | | vm.startPrank(msgSender, origin);
697 | | }
698 | |
699 | | function changePrank(address msgSender) internal virtual {
700 | | console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
701 | | vm.stopPrank();
702 | | vm.startPrank(msgSender);
703 | | }
704 | |
705 | | function changePrank(address msgSender, address txOrigin) internal virtual {
706 | | vm.stopPrank();
707 | | vm.startPrank(msgSender, txOrigin);
708 | | }
709 | |
710 | | // The same as Vm's `deal`
711 | | // Use the alternative signature for ERC20 tokens
712 | | function deal(address to, uint256 give) internal virtual {
713 | | vm.deal(to, give);
714 | | }
715 | |
716 | | // Set the balance of an account for any ERC20 token
717 | | // Use the alternative signature to update `totalSupply`
718 | | function deal(address token, address to, uint256 give) internal virtual {
719 | | deal(token, to, give, false);
720 | | }
721 | |
722 | | // Set the balance of an account for any ERC1155 token
723 | | // Use the alternative signature to update `totalSupply`
724 | | function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
725 | | dealERC1155(token, to, id, give, false);
726 | | }
727 | |
728 | | function deal(address token, address to, uint256 give, bool adjust) internal virtual {
729 | | // get current balance
730 | | (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
731 | | uint256 prevBal = abi.decode(balData, (uint256));
732 | |
733 | | // update balance
734 | | stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
735 | |
736 | | // update total supply
737 | | if (adjust) {
738 | | (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
739 | | uint256 totSup = abi.decode(totSupData, (uint256));
740 | | if (give < prevBal) {
741 | | totSup -= (prevBal - give);
742 | | } else {
743 | | totSup += (give - prevBal);
744 | | }
745 | | stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
746 | | }
747 | | }
748 | |
749 | | function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
750 | | // get current balance
751 | | (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
752 | | uint256 prevBal = abi.decode(balData, (uint256));
753 | |
754 | | // update balance
755 | | stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
756 | |
757 | | // update total supply
758 | | if (adjust) {
759 | | (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
760 | | require(
761 | | totSupData.length != 0,
762 | | "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
763 | | );
764 | | uint256 totSup = abi.decode(totSupData, (uint256));
765 | | if (give < prevBal) {
766 | | totSup -= (prevBal - give);
767 | | } else {
768 | | totSup += (give - prevBal);
769 | | }
770 | | stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
771 | | }
772 | | }
773 | |
774 | | function dealERC721(address token, address to, uint256 id) internal virtual {
775 | | // check if token id is already minted and the actual owner.
776 | | (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
777 | | require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
778 | |
779 | | // get owner current balance
780 | | (, bytes memory fromBalData) =
781 | | token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
782 | | uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
783 | |
784 | | // get new user current balance
785 | | (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
786 | | uint256 toPrevBal = abi.decode(toBalData, (uint256));
787 | |
788 | | // update balances
789 | | stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
790 | | stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
791 | |
792 | | // update owner
793 | | stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
794 | | }
795 | |
796 | | function deployCodeTo(string memory what, address where) internal virtual {
797 | | deployCodeTo(what, "", 0, where);
798 | | }
799 | |
800 | | function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
801 | | deployCodeTo(what, args, 0, where);
802 | | }
803 | |
804 | | function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
805 | | bytes memory creationCode = vm.getCode(what);
806 | | vm.etch(where, abi.encodePacked(creationCode, args));
807 | | (bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
808 | | require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
809 | | vm.etch(where, runtimeBytecode);
810 | | }
811 | |
812 | | // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
813 | | function console2_log_StdCheats(string memory p0) private view {
814 | | (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
815 | | status;
816 | | }
817 | | }
818 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdError.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test
3 | | pragma solidity >=0.6.2 <0.9.0;
4 | |
5 | | library stdError {
6 | | bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
7 | | bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
8 | | bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
9 | | bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
10 | | bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
11 | | bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
12 | | bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
13 | | bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
14 | | bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
15 | | }
16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdInvariant.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | abstract contract StdInvariant {
7 | | struct FuzzSelector {
8 | | address addr;
9 | | bytes4[] selectors;
10 | | }
11 | |
12 | | struct FuzzArtifactSelector {
13 | | string artifact;
14 | | bytes4[] selectors;
15 | | }
16 | |
17 | | struct FuzzInterface {
18 | | address addr;
19 | | string[] artifacts;
20 | | }
21 | |
22 | | address[] private _excludedContracts;
23 | | address[] private _excludedSenders;
24 | | address[] private _targetedContracts;
25 | | address[] private _targetedSenders;
26 | |
27 | | string[] private _excludedArtifacts;
28 | | string[] private _targetedArtifacts;
29 | |
30 | | FuzzArtifactSelector[] private _targetedArtifactSelectors;
31 | |
32 | | FuzzSelector[] private _excludedSelectors;
33 | | FuzzSelector[] private _targetedSelectors;
34 | |
35 | | FuzzInterface[] private _targetedInterfaces;
36 | |
37 | | // Functions for users:
38 | | // These are intended to be called in tests.
39 | |
40 | | function excludeContract(address newExcludedContract_) internal {
41 | | _excludedContracts.push(newExcludedContract_);
42 | | }
43 | |
44 | | function excludeSelector(FuzzSelector memory newExcludedSelector_) internal {
45 | | _excludedSelectors.push(newExcludedSelector_);
46 | | }
47 | |
48 | | function excludeSender(address newExcludedSender_) internal {
49 | | _excludedSenders.push(newExcludedSender_);
50 | | }
51 | |
52 | | function excludeArtifact(string memory newExcludedArtifact_) internal {
53 | | _excludedArtifacts.push(newExcludedArtifact_);
54 | | }
55 | |
56 | | function targetArtifact(string memory newTargetedArtifact_) internal {
57 | | _targetedArtifacts.push(newTargetedArtifact_);
58 | | }
59 | |
60 | | function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal {
61 | | _targetedArtifactSelectors.push(newTargetedArtifactSelector_);
62 | | }
63 | |
64 | | function targetContract(address newTargetedContract_) internal {
65 | | _targetedContracts.push(newTargetedContract_);
66 | | }
67 | |
68 | | function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
69 | | _targetedSelectors.push(newTargetedSelector_);
70 | | }
71 | |
72 | | function targetSender(address newTargetedSender_) internal {
73 | | _targetedSenders.push(newTargetedSender_);
74 | | }
75 | |
76 | | function targetInterface(FuzzInterface memory newTargetedInterface_) internal {
77 | | _targetedInterfaces.push(newTargetedInterface_);
78 | | }
79 | |
80 | | // Functions for forge:
81 | | // These are called by forge to run invariant tests and don't need to be called in tests.
82 | |
83 | * | function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
84 | * | excludedArtifacts_ = _excludedArtifacts;
85 | | }
86 | |
87 | * | function excludeContracts() public view returns (address[] memory excludedContracts_) {
88 | * | excludedContracts_ = _excludedContracts;
89 | | }
90 | |
91 | * | function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) {
92 | * | excludedSelectors_ = _excludedSelectors;
93 | | }
94 | |
95 | * | function excludeSenders() public view returns (address[] memory excludedSenders_) {
96 | * | excludedSenders_ = _excludedSenders;
97 | | }
98 | |
99 | * | function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
100 | * | targetedArtifacts_ = _targetedArtifacts;
101 | | }
102 | |
103 | * | function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) {
104 | * | targetedArtifactSelectors_ = _targetedArtifactSelectors;
105 | | }
106 | |
107 | * | function targetContracts() public view returns (address[] memory targetedContracts_) {
108 | * | targetedContracts_ = _targetedContracts;
109 | | }
110 | |
111 | * | function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
112 | * | targetedSelectors_ = _targetedSelectors;
113 | | }
114 | |
115 | * | function targetSenders() public view returns (address[] memory targetedSenders_) {
116 | * | targetedSenders_ = _targetedSenders;
117 | | }
118 | |
119 | * | function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) {
120 | * | targetedInterfaces_ = _targetedInterfaces;
121 | | }
122 | | }
123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdJson.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.0 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | import {VmSafe} from "./Vm.sol";
7 | |
8 | | // Helpers for parsing and writing JSON files
9 | | // To parse:
10 | | // ```
11 | | // using stdJson for string;
12 | | // string memory json = vm.readFile("<some_path>");
13 | | // json.readUint("<json_path>");
14 | | // ```
15 | | // To write:
16 | | // ```
17 | | // using stdJson for string;
18 | | // string memory json = "json";
19 | | // json.serialize("a", uint256(123));
20 | | // string memory semiFinal = json.serialize("b", string("test"));
21 | | // string memory finalJson = json.serialize("c", semiFinal);
22 | | // finalJson.write("<some_path>");
23 | | // ```
24 | |
25 | * | library stdJson {
26 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
27 | |
28 | | function keyExists(string memory json, string memory key) internal view returns (bool) {
29 | | return vm.keyExistsJson(json, key);
30 | | }
31 | |
32 | | function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
33 | | return vm.parseJson(json, key);
34 | | }
35 | |
36 | | function readUint(string memory json, string memory key) internal pure returns (uint256) {
37 | | return vm.parseJsonUint(json, key);
38 | | }
39 | |
40 | | function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
41 | | return vm.parseJsonUintArray(json, key);
42 | | }
43 | |
44 | | function readInt(string memory json, string memory key) internal pure returns (int256) {
45 | | return vm.parseJsonInt(json, key);
46 | | }
47 | |
48 | | function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
49 | | return vm.parseJsonIntArray(json, key);
50 | | }
51 | |
52 | | function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
53 | | return vm.parseJsonBytes32(json, key);
54 | | }
55 | |
56 | | function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
57 | | return vm.parseJsonBytes32Array(json, key);
58 | | }
59 | |
60 | | function readString(string memory json, string memory key) internal pure returns (string memory) {
61 | | return vm.parseJsonString(json, key);
62 | | }
63 | |
64 | | function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
65 | | return vm.parseJsonStringArray(json, key);
66 | | }
67 | |
68 | | function readAddress(string memory json, string memory key) internal pure returns (address) {
69 | | return vm.parseJsonAddress(json, key);
70 | | }
71 | |
72 | | function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
73 | | return vm.parseJsonAddressArray(json, key);
74 | | }
75 | |
76 | | function readBool(string memory json, string memory key) internal pure returns (bool) {
77 | | return vm.parseJsonBool(json, key);
78 | | }
79 | |
80 | | function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
81 | | return vm.parseJsonBoolArray(json, key);
82 | | }
83 | |
84 | | function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
85 | | return vm.parseJsonBytes(json, key);
86 | | }
87 | |
88 | | function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
89 | | return vm.parseJsonBytesArray(json, key);
90 | | }
91 | |
92 | | function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) {
93 | | return keyExists(json, key) ? readUint(json, key) : defaultValue;
94 | | }
95 | |
96 | | function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue)
97 | | internal
98 | | view
99 | | returns (uint256[] memory)
100 | | {
101 | | return keyExists(json, key) ? readUintArray(json, key) : defaultValue;
102 | | }
103 | |
104 | | function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) {
105 | | return keyExists(json, key) ? readInt(json, key) : defaultValue;
106 | | }
107 | |
108 | | function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue)
109 | | internal
110 | | view
111 | | returns (int256[] memory)
112 | | {
113 | | return keyExists(json, key) ? readIntArray(json, key) : defaultValue;
114 | | }
115 | |
116 | | function readBytes32Or(string memory json, string memory key, bytes32 defaultValue)
117 | | internal
118 | | view
119 | | returns (bytes32)
120 | | {
121 | | return keyExists(json, key) ? readBytes32(json, key) : defaultValue;
122 | | }
123 | |
124 | | function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue)
125 | | internal
126 | | view
127 | | returns (bytes32[] memory)
128 | | {
129 | | return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue;
130 | | }
131 | |
132 | | function readStringOr(string memory json, string memory key, string memory defaultValue)
133 | | internal
134 | | view
135 | | returns (string memory)
136 | | {
137 | | return keyExists(json, key) ? readString(json, key) : defaultValue;
138 | | }
139 | |
140 | | function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue)
141 | | internal
142 | | view
143 | | returns (string[] memory)
144 | | {
145 | | return keyExists(json, key) ? readStringArray(json, key) : defaultValue;
146 | | }
147 | |
148 | | function readAddressOr(string memory json, string memory key, address defaultValue)
149 | | internal
150 | | view
151 | | returns (address)
152 | | {
153 | | return keyExists(json, key) ? readAddress(json, key) : defaultValue;
154 | | }
155 | |
156 | | function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue)
157 | | internal
158 | | view
159 | | returns (address[] memory)
160 | | {
161 | | return keyExists(json, key) ? readAddressArray(json, key) : defaultValue;
162 | | }
163 | |
164 | | function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) {
165 | | return keyExists(json, key) ? readBool(json, key) : defaultValue;
166 | | }
167 | |
168 | | function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue)
169 | | internal
170 | | view
171 | | returns (bool[] memory)
172 | | {
173 | | return keyExists(json, key) ? readBoolArray(json, key) : defaultValue;
174 | | }
175 | |
176 | | function readBytesOr(string memory json, string memory key, bytes memory defaultValue)
177 | | internal
178 | | view
179 | | returns (bytes memory)
180 | | {
181 | | return keyExists(json, key) ? readBytes(json, key) : defaultValue;
182 | | }
183 | |
184 | | function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue)
185 | | internal
186 | | view
187 | | returns (bytes[] memory)
188 | | {
189 | | return keyExists(json, key) ? readBytesArray(json, key) : defaultValue;
190 | | }
191 | |
192 | | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
193 | | return vm.serializeJson(jsonKey, rootObject);
194 | | }
195 | |
196 | | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
197 | | return vm.serializeBool(jsonKey, key, value);
198 | | }
199 | |
200 | | function serialize(string memory jsonKey, string memory key, bool[] memory value)
201 | | internal
202 | | returns (string memory)
203 | | {
204 | | return vm.serializeBool(jsonKey, key, value);
205 | | }
206 | |
207 | | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
208 | | return vm.serializeUint(jsonKey, key, value);
209 | | }
210 | |
211 | | function serialize(string memory jsonKey, string memory key, uint256[] memory value)
212 | | internal
213 | | returns (string memory)
214 | | {
215 | | return vm.serializeUint(jsonKey, key, value);
216 | | }
217 | |
218 | | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
219 | | return vm.serializeInt(jsonKey, key, value);
220 | | }
221 | |
222 | | function serialize(string memory jsonKey, string memory key, int256[] memory value)
223 | | internal
224 | | returns (string memory)
225 | | {
226 | | return vm.serializeInt(jsonKey, key, value);
227 | | }
228 | |
229 | | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
230 | | return vm.serializeAddress(jsonKey, key, value);
231 | | }
232 | |
233 | | function serialize(string memory jsonKey, string memory key, address[] memory value)
234 | | internal
235 | | returns (string memory)
236 | | {
237 | | return vm.serializeAddress(jsonKey, key, value);
238 | | }
239 | |
240 | | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
241 | | return vm.serializeBytes32(jsonKey, key, value);
242 | | }
243 | |
244 | | function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
245 | | internal
246 | | returns (string memory)
247 | | {
248 | | return vm.serializeBytes32(jsonKey, key, value);
249 | | }
250 | |
251 | | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
252 | | return vm.serializeBytes(jsonKey, key, value);
253 | | }
254 | |
255 | | function serialize(string memory jsonKey, string memory key, bytes[] memory value)
256 | | internal
257 | | returns (string memory)
258 | | {
259 | | return vm.serializeBytes(jsonKey, key, value);
260 | | }
261 | |
262 | | function serialize(string memory jsonKey, string memory key, string memory value)
263 | | internal
264 | | returns (string memory)
265 | | {
266 | | return vm.serializeString(jsonKey, key, value);
267 | | }
268 | |
269 | | function serialize(string memory jsonKey, string memory key, string[] memory value)
270 | | internal
271 | | returns (string memory)
272 | | {
273 | | return vm.serializeString(jsonKey, key, value);
274 | | }
275 | |
276 | | function write(string memory jsonKey, string memory path) internal {
277 | | vm.writeJson(jsonKey, path);
278 | | }
279 | |
280 | | function write(string memory jsonKey, string memory path, string memory valueKey) internal {
281 | | vm.writeJson(jsonKey, path, valueKey);
282 | | }
283 | | }
284 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdMath.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | * | library stdMath {
5 | | int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
6 | |
7 | | function abs(int256 a) internal pure returns (uint256) {
8 | | // Required or it will fail when `a = type(int256).min`
9 | | if (a == INT256_MIN) {
10 | | return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
11 | | }
12 | |
13 | | return uint256(a > 0 ? a : -a);
14 | | }
15 | |
16 | | function delta(uint256 a, uint256 b) internal pure returns (uint256) {
17 | | return a > b ? a - b : b - a;
18 | | }
19 | |
20 | | function delta(int256 a, int256 b) internal pure returns (uint256) {
21 | | // a and b are of the same sign
22 | | // this works thanks to two's complement, the left-most bit is the sign bit
23 | | if ((a ^ b) > -1) {
24 | | return delta(abs(a), abs(b));
25 | | }
26 | |
27 | | // a and b are of opposite signs
28 | | return abs(a) + abs(b);
29 | | }
30 | |
31 | | function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
32 | | uint256 absDelta = delta(a, b);
33 | |
34 | | return absDelta * 1e18 / b;
35 | | }
36 | |
37 | | function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
38 | | uint256 absDelta = delta(a, b);
39 | | uint256 absB = abs(b);
40 | |
41 | | return absDelta * 1e18 / absB;
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdStorage.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | import {Vm} from "./Vm.sol";
5 | |
6 | | struct FindData {
7 | | uint256 slot;
8 | | uint256 offsetLeft;
9 | | uint256 offsetRight;
10 | | bool found;
11 | | }
12 | |
13 | | struct StdStorage {
14 | | mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds;
15 | | bytes32[] _keys;
16 | | bytes4 _sig;
17 | | uint256 _depth;
18 | | address _target;
19 | | bytes32 _set;
20 | | bool _enable_packed_slots;
21 | | bytes _calldata;
22 | | }
23 | |
24 | * | library stdStorageSafe {
25 | | event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
26 | | event WARNING_UninitedSlot(address who, uint256 slot);
27 | |
28 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
29 | | uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
30 | |
31 | | function sigs(string memory sigStr) internal pure returns (bytes4) {
32 | | return bytes4(keccak256(bytes(sigStr)));
33 | | }
34 | |
35 | | function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
36 | | if (self._calldata.length == 0) {
37 | | return flatten(self._keys);
38 | | } else {
39 | | return self._calldata;
40 | | }
41 | | }
42 | |
43 | | // Calls target contract with configured parameters
44 | | function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
45 | | bytes memory cald = abi.encodePacked(self._sig, getCallParams(self));
46 | | (bool success, bytes memory rdat) = self._target.staticcall(cald);
47 | | bytes32 result = bytesToBytes32(rdat, 32 * self._depth);
48 | |
49 | | return (success, result);
50 | | }
51 | |
52 | | // Tries mutating slot value to determine if the targeted value is stored in it.
53 | | // If current value is 0, then we are setting slot value to type(uint256).max
54 | | // Otherwise, we set it to 0. That way, return value should always be affected.
55 | | function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
56 | | bytes32 prevSlotValue = vm.load(self._target, slot);
57 | | (bool success, bytes32 prevReturnValue) = callTarget(self);
58 | |
59 | | bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
60 | | vm.store(self._target, slot, testVal);
61 | |
62 | | (, bytes32 newReturnValue) = callTarget(self);
63 | |
64 | | vm.store(self._target, slot, prevSlotValue);
65 | |
66 | | return (success && (prevReturnValue != newReturnValue));
67 | | }
68 | |
69 | | // Tries setting one of the bits in slot to 1 until return value changes.
70 | | // Index of resulted bit is an offset packed slot has from left/right side
71 | | function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
72 | | for (uint256 offset = 0; offset < 256; offset++) {
73 | | uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset);
74 | | vm.store(self._target, slot, bytes32(valueToPut));
75 | |
76 | | (bool success, bytes32 data) = callTarget(self);
77 | |
78 | | if (success && (uint256(data) > 0)) {
79 | | return (true, offset);
80 | | }
81 | | }
82 | | return (false, 0);
83 | | }
84 | |
85 | | function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
86 | | bytes32 prevSlotValue = vm.load(self._target, slot);
87 | |
88 | | (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
89 | | (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
90 | |
91 | | // `findOffset` may mutate slot value, so we are setting it to initial value
92 | | vm.store(self._target, slot, prevSlotValue);
93 | | return (foundLeft && foundRight, offsetLeft, offsetRight);
94 | | }
95 | |
96 | | function find(StdStorage storage self) internal returns (FindData storage) {
97 | | return find(self, true);
98 | | }
99 | |
100 | | /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
101 | | // slot complexity:
102 | | // if flat, will be bytes32(uint256(uint));
103 | | // if map, will be keccak256(abi.encode(key, uint(slot)));
104 | | // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
105 | | // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
106 | | function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
107 | | address who = self._target;
108 | | bytes4 fsig = self._sig;
109 | | uint256 field_depth = self._depth;
110 | | bytes memory params = getCallParams(self);
111 | |
112 | | // calldata to test against
113 | | if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
114 | | if (_clear) {
115 | | clear(self);
116 | | }
117 | | return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
118 | | }
119 | | vm.record();
120 | | (, bytes32 callResult) = callTarget(self);
121 | | (bytes32[] memory reads,) = vm.accesses(address(who));
122 | |
123 | | if (reads.length == 0) {
124 | | revert("stdStorage find(StdStorage): No storage use detected for target.");
125 | | } else {
126 | | for (uint256 i = reads.length; --i >= 0;) {
127 | | bytes32 prev = vm.load(who, reads[i]);
128 | | if (prev == bytes32(0)) {
129 | | emit WARNING_UninitedSlot(who, uint256(reads[i]));
130 | | }
131 | |
132 | | if (!checkSlotMutatesCall(self, reads[i])) {
133 | | continue;
134 | | }
135 | |
136 | | (uint256 offsetLeft, uint256 offsetRight) = (0, 0);
137 | |
138 | | if (self._enable_packed_slots) {
139 | | bool found;
140 | | (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
141 | | if (!found) {
142 | | continue;
143 | | }
144 | | }
145 | |
146 | | // Check that value between found offsets is equal to the current call result
147 | | uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
148 | |
149 | | if (uint256(callResult) != curVal) {
150 | | continue;
151 | | }
152 | |
153 | | emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
154 | | self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
155 | | FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
156 | | break;
157 | | }
158 | | }
159 | |
160 | | require(
161 | | self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
162 | | "stdStorage find(StdStorage): Slot(s) not found."
163 | | );
164 | |
165 | | if (_clear) {
166 | | clear(self);
167 | | }
168 | | return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
169 | | }
170 | |
171 | | function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
172 | | self._target = _target;
173 | | return self;
174 | | }
175 | |
176 | | function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
177 | | self._sig = _sig;
178 | | return self;
179 | | }
180 | |
181 | | function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
182 | | self._sig = sigs(_sig);
183 | | return self;
184 | | }
185 | |
186 | | function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
187 | | self._calldata = _calldata;
188 | | return self;
189 | | }
190 | |
191 | | function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
192 | | self._keys.push(bytes32(uint256(uint160(who))));
193 | | return self;
194 | | }
195 | |
196 | | function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
197 | | self._keys.push(bytes32(amt));
198 | | return self;
199 | | }
200 | |
201 | | function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
202 | | self._keys.push(key);
203 | | return self;
204 | | }
205 | |
206 | | function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
207 | | self._enable_packed_slots = true;
208 | | return self;
209 | | }
210 | |
211 | | function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
212 | | self._depth = _depth;
213 | | return self;
214 | | }
215 | |
216 | | function read(StdStorage storage self) private returns (bytes memory) {
217 | | FindData storage data = find(self, false);
218 | | uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
219 | | uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
220 | | clear(self);
221 | | return abi.encode(value);
222 | | }
223 | |
224 | | function read_bytes32(StdStorage storage self) internal returns (bytes32) {
225 | | return abi.decode(read(self), (bytes32));
226 | | }
227 | |
228 | | function read_bool(StdStorage storage self) internal returns (bool) {
229 | | int256 v = read_int(self);
230 | | if (v == 0) return false;
231 | | if (v == 1) return true;
232 | | revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
233 | | }
234 | |
235 | | function read_address(StdStorage storage self) internal returns (address) {
236 | | return abi.decode(read(self), (address));
237 | | }
238 | |
239 | | function read_uint(StdStorage storage self) internal returns (uint256) {
240 | | return abi.decode(read(self), (uint256));
241 | | }
242 | |
243 | | function read_int(StdStorage storage self) internal returns (int256) {
244 | | return abi.decode(read(self), (int256));
245 | | }
246 | |
247 | | function parent(StdStorage storage self) internal returns (uint256, bytes32) {
248 | | address who = self._target;
249 | | uint256 field_depth = self._depth;
250 | | vm.startMappingRecording();
251 | | uint256 child = find(self, true).slot - field_depth;
252 | | (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
253 | | if (!found) {
254 | | revert(
255 | | "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
256 | | );
257 | | }
258 | | return (uint256(parent_slot), key);
259 | | }
260 | |
261 | | function root(StdStorage storage self) internal returns (uint256) {
262 | | address who = self._target;
263 | | uint256 field_depth = self._depth;
264 | | vm.startMappingRecording();
265 | | uint256 child = find(self, true).slot - field_depth;
266 | | bool found;
267 | | bytes32 root_slot;
268 | | bytes32 parent_slot;
269 | | (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
270 | | if (!found) {
271 | | revert(
272 | | "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
273 | | );
274 | | }
275 | | while (found) {
276 | | root_slot = parent_slot;
277 | | (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
278 | | }
279 | | return uint256(root_slot);
280 | | }
281 | |
282 | | function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
283 | | bytes32 out;
284 | |
285 | | uint256 max = b.length > 32 ? 32 : b.length;
286 | | for (uint256 i = 0; i < max; i++) {
287 | | out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
288 | | }
289 | | return out;
290 | | }
291 | |
292 | | function flatten(bytes32[] memory b) private pure returns (bytes memory) {
293 | | bytes memory result = new bytes(b.length * 32);
294 | | for (uint256 i = 0; i < b.length; i++) {
295 | | bytes32 k = b[i];
296 | | /// @solidity memory-safe-assembly
297 | | assembly {
298 | | mstore(add(result, add(32, mul(32, i))), k)
299 | | }
300 | | }
301 | |
302 | | return result;
303 | | }
304 | |
305 | | function clear(StdStorage storage self) internal {
306 | | delete self._target;
307 | | delete self._sig;
308 | | delete self._keys;
309 | | delete self._depth;
310 | | delete self._enable_packed_slots;
311 | | delete self._calldata;
312 | | }
313 | |
314 | | // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`
315 | | // (slotValue & mask) >> offsetRight will be the value of the given packed variable
316 | | function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
317 | | // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;
318 | | // using assembly because (1 << 256) causes overflow
319 | | assembly {
320 | | mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
321 | | }
322 | | }
323 | |
324 | | // Returns slot value with updated packed variable.
325 | | function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
326 | | internal
327 | | pure
328 | | returns (bytes32 newValue)
329 | | {
330 | | return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
331 | | }
332 | | }
333 | |
334 | * | library stdStorage {
335 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
336 | |
337 | | function sigs(string memory sigStr) internal pure returns (bytes4) {
338 | | return stdStorageSafe.sigs(sigStr);
339 | | }
340 | |
341 | | function find(StdStorage storage self) internal returns (uint256) {
342 | | return find(self, true);
343 | | }
344 | |
345 | | function find(StdStorage storage self, bool _clear) internal returns (uint256) {
346 | | return stdStorageSafe.find(self, _clear).slot;
347 | | }
348 | |
349 | | function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
350 | | return stdStorageSafe.target(self, _target);
351 | | }
352 | |
353 | | function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
354 | | return stdStorageSafe.sig(self, _sig);
355 | | }
356 | |
357 | | function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
358 | | return stdStorageSafe.sig(self, _sig);
359 | | }
360 | |
361 | | function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
362 | | return stdStorageSafe.with_key(self, who);
363 | | }
364 | |
365 | | function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
366 | | return stdStorageSafe.with_key(self, amt);
367 | | }
368 | |
369 | | function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
370 | | return stdStorageSafe.with_key(self, key);
371 | | }
372 | |
373 | | function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
374 | | return stdStorageSafe.with_calldata(self, _calldata);
375 | | }
376 | |
377 | | function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
378 | | return stdStorageSafe.enable_packed_slots(self);
379 | | }
380 | |
381 | | function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
382 | | return stdStorageSafe.depth(self, _depth);
383 | | }
384 | |
385 | | function clear(StdStorage storage self) internal {
386 | | stdStorageSafe.clear(self);
387 | | }
388 | |
389 | | function checked_write(StdStorage storage self, address who) internal {
390 | | checked_write(self, bytes32(uint256(uint160(who))));
391 | | }
392 | |
393 | | function checked_write(StdStorage storage self, uint256 amt) internal {
394 | | checked_write(self, bytes32(amt));
395 | | }
396 | |
397 | | function checked_write_int(StdStorage storage self, int256 val) internal {
398 | | checked_write(self, bytes32(uint256(val)));
399 | | }
400 | |
401 | | function checked_write(StdStorage storage self, bool write) internal {
402 | | bytes32 t;
403 | | /// @solidity memory-safe-assembly
404 | | assembly {
405 | | t := write
406 | | }
407 | | checked_write(self, t);
408 | | }
409 | |
410 | | function checked_write(StdStorage storage self, bytes32 set) internal {
411 | | address who = self._target;
412 | | bytes4 fsig = self._sig;
413 | | uint256 field_depth = self._depth;
414 | | bytes memory params = stdStorageSafe.getCallParams(self);
415 | |
416 | | if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
417 | | find(self, false);
418 | | }
419 | | FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
420 | | if ((data.offsetLeft + data.offsetRight) > 0) {
421 | | uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight));
422 | | require(
423 | | uint256(set) < maxVal,
424 | | string(
425 | | abi.encodePacked(
426 | | "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
427 | | vm.toString(maxVal)
428 | | )
429 | | )
430 | | );
431 | | }
432 | | bytes32 curVal = vm.load(who, bytes32(data.slot));
433 | | bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
434 | |
435 | | vm.store(who, bytes32(data.slot), valToSet);
436 | |
437 | | (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
438 | |
439 | | if (!success || callResult != set) {
440 | | vm.store(who, bytes32(data.slot), curVal);
441 | | revert("stdStorage find(StdStorage): Failed to write value.");
442 | | }
443 | | clear(self);
444 | | }
445 | |
446 | | function read_bytes32(StdStorage storage self) internal returns (bytes32) {
447 | | return stdStorageSafe.read_bytes32(self);
448 | | }
449 | |
450 | | function read_bool(StdStorage storage self) internal returns (bool) {
451 | | return stdStorageSafe.read_bool(self);
452 | | }
453 | |
454 | | function read_address(StdStorage storage self) internal returns (address) {
455 | | return stdStorageSafe.read_address(self);
456 | | }
457 | |
458 | | function read_uint(StdStorage storage self) internal returns (uint256) {
459 | | return stdStorageSafe.read_uint(self);
460 | | }
461 | |
462 | | function read_int(StdStorage storage self) internal returns (int256) {
463 | | return stdStorageSafe.read_int(self);
464 | | }
465 | |
466 | | function parent(StdStorage storage self) internal returns (uint256, bytes32) {
467 | | return stdStorageSafe.parent(self);
468 | | }
469 | |
470 | | function root(StdStorage storage self) internal returns (uint256) {
471 | | return stdStorageSafe.root(self);
472 | | }
473 | | }
474 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdStyle.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.4.22 <0.9.0;
3 | |
4 | | import {VmSafe} from "./Vm.sol";
5 | |
6 | * | library StdStyle {
7 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
8 | |
9 | | string constant RED = "\u001b[91m";
10 | | string constant GREEN = "\u001b[92m";
11 | | string constant YELLOW = "\u001b[93m";
12 | | string constant BLUE = "\u001b[94m";
13 | | string constant MAGENTA = "\u001b[95m";
14 | | string constant CYAN = "\u001b[96m";
15 | | string constant BOLD = "\u001b[1m";
16 | | string constant DIM = "\u001b[2m";
17 | | string constant ITALIC = "\u001b[3m";
18 | | string constant UNDERLINE = "\u001b[4m";
19 | | string constant INVERSE = "\u001b[7m";
20 | | string constant RESET = "\u001b[0m";
21 | |
22 | | function styleConcat(string memory style, string memory self) private pure returns (string memory) {
23 | | return string(abi.encodePacked(style, self, RESET));
24 | | }
25 | |
26 | | function red(string memory self) internal pure returns (string memory) {
27 | | return styleConcat(RED, self);
28 | | }
29 | |
30 | | function red(uint256 self) internal pure returns (string memory) {
31 | | return red(vm.toString(self));
32 | | }
33 | |
34 | | function red(int256 self) internal pure returns (string memory) {
35 | | return red(vm.toString(self));
36 | | }
37 | |
38 | | function red(address self) internal pure returns (string memory) {
39 | | return red(vm.toString(self));
40 | | }
41 | |
42 | | function red(bool self) internal pure returns (string memory) {
43 | | return red(vm.toString(self));
44 | | }
45 | |
46 | | function redBytes(bytes memory self) internal pure returns (string memory) {
47 | | return red(vm.toString(self));
48 | | }
49 | |
50 | | function redBytes32(bytes32 self) internal pure returns (string memory) {
51 | | return red(vm.toString(self));
52 | | }
53 | |
54 | | function green(string memory self) internal pure returns (string memory) {
55 | | return styleConcat(GREEN, self);
56 | | }
57 | |
58 | | function green(uint256 self) internal pure returns (string memory) {
59 | | return green(vm.toString(self));
60 | | }
61 | |
62 | | function green(int256 self) internal pure returns (string memory) {
63 | | return green(vm.toString(self));
64 | | }
65 | |
66 | | function green(address self) internal pure returns (string memory) {
67 | | return green(vm.toString(self));
68 | | }
69 | |
70 | | function green(bool self) internal pure returns (string memory) {
71 | | return green(vm.toString(self));
72 | | }
73 | |
74 | | function greenBytes(bytes memory self) internal pure returns (string memory) {
75 | | return green(vm.toString(self));
76 | | }
77 | |
78 | | function greenBytes32(bytes32 self) internal pure returns (string memory) {
79 | | return green(vm.toString(self));
80 | | }
81 | |
82 | | function yellow(string memory self) internal pure returns (string memory) {
83 | | return styleConcat(YELLOW, self);
84 | | }
85 | |
86 | | function yellow(uint256 self) internal pure returns (string memory) {
87 | | return yellow(vm.toString(self));
88 | | }
89 | |
90 | | function yellow(int256 self) internal pure returns (string memory) {
91 | | return yellow(vm.toString(self));
92 | | }
93 | |
94 | | function yellow(address self) internal pure returns (string memory) {
95 | | return yellow(vm.toString(self));
96 | | }
97 | |
98 | | function yellow(bool self) internal pure returns (string memory) {
99 | | return yellow(vm.toString(self));
100 | | }
101 | |
102 | | function yellowBytes(bytes memory self) internal pure returns (string memory) {
103 | | return yellow(vm.toString(self));
104 | | }
105 | |
106 | | function yellowBytes32(bytes32 self) internal pure returns (string memory) {
107 | | return yellow(vm.toString(self));
108 | | }
109 | |
110 | | function blue(string memory self) internal pure returns (string memory) {
111 | | return styleConcat(BLUE, self);
112 | | }
113 | |
114 | | function blue(uint256 self) internal pure returns (string memory) {
115 | | return blue(vm.toString(self));
116 | | }
117 | |
118 | | function blue(int256 self) internal pure returns (string memory) {
119 | | return blue(vm.toString(self));
120 | | }
121 | |
122 | | function blue(address self) internal pure returns (string memory) {
123 | | return blue(vm.toString(self));
124 | | }
125 | |
126 | | function blue(bool self) internal pure returns (string memory) {
127 | | return blue(vm.toString(self));
128 | | }
129 | |
130 | | function blueBytes(bytes memory self) internal pure returns (string memory) {
131 | | return blue(vm.toString(self));
132 | | }
133 | |
134 | | function blueBytes32(bytes32 self) internal pure returns (string memory) {
135 | | return blue(vm.toString(self));
136 | | }
137 | |
138 | | function magenta(string memory self) internal pure returns (string memory) {
139 | | return styleConcat(MAGENTA, self);
140 | | }
141 | |
142 | | function magenta(uint256 self) internal pure returns (string memory) {
143 | | return magenta(vm.toString(self));
144 | | }
145 | |
146 | | function magenta(int256 self) internal pure returns (string memory) {
147 | | return magenta(vm.toString(self));
148 | | }
149 | |
150 | | function magenta(address self) internal pure returns (string memory) {
151 | | return magenta(vm.toString(self));
152 | | }
153 | |
154 | | function magenta(bool self) internal pure returns (string memory) {
155 | | return magenta(vm.toString(self));
156 | | }
157 | |
158 | | function magentaBytes(bytes memory self) internal pure returns (string memory) {
159 | | return magenta(vm.toString(self));
160 | | }
161 | |
162 | | function magentaBytes32(bytes32 self) internal pure returns (string memory) {
163 | | return magenta(vm.toString(self));
164 | | }
165 | |
166 | | function cyan(string memory self) internal pure returns (string memory) {
167 | | return styleConcat(CYAN, self);
168 | | }
169 | |
170 | | function cyan(uint256 self) internal pure returns (string memory) {
171 | | return cyan(vm.toString(self));
172 | | }
173 | |
174 | | function cyan(int256 self) internal pure returns (string memory) {
175 | | return cyan(vm.toString(self));
176 | | }
177 | |
178 | | function cyan(address self) internal pure returns (string memory) {
179 | | return cyan(vm.toString(self));
180 | | }
181 | |
182 | | function cyan(bool self) internal pure returns (string memory) {
183 | | return cyan(vm.toString(self));
184 | | }
185 | |
186 | | function cyanBytes(bytes memory self) internal pure returns (string memory) {
187 | | return cyan(vm.toString(self));
188 | | }
189 | |
190 | | function cyanBytes32(bytes32 self) internal pure returns (string memory) {
191 | | return cyan(vm.toString(self));
192 | | }
193 | |
194 | | function bold(string memory self) internal pure returns (string memory) {
195 | | return styleConcat(BOLD, self);
196 | | }
197 | |
198 | | function bold(uint256 self) internal pure returns (string memory) {
199 | | return bold(vm.toString(self));
200 | | }
201 | |
202 | | function bold(int256 self) internal pure returns (string memory) {
203 | | return bold(vm.toString(self));
204 | | }
205 | |
206 | | function bold(address self) internal pure returns (string memory) {
207 | | return bold(vm.toString(self));
208 | | }
209 | |
210 | | function bold(bool self) internal pure returns (string memory) {
211 | | return bold(vm.toString(self));
212 | | }
213 | |
214 | | function boldBytes(bytes memory self) internal pure returns (string memory) {
215 | | return bold(vm.toString(self));
216 | | }
217 | |
218 | | function boldBytes32(bytes32 self) internal pure returns (string memory) {
219 | | return bold(vm.toString(self));
220 | | }
221 | |
222 | | function dim(string memory self) internal pure returns (string memory) {
223 | | return styleConcat(DIM, self);
224 | | }
225 | |
226 | | function dim(uint256 self) internal pure returns (string memory) {
227 | | return dim(vm.toString(self));
228 | | }
229 | |
230 | | function dim(int256 self) internal pure returns (string memory) {
231 | | return dim(vm.toString(self));
232 | | }
233 | |
234 | | function dim(address self) internal pure returns (string memory) {
235 | | return dim(vm.toString(self));
236 | | }
237 | |
238 | | function dim(bool self) internal pure returns (string memory) {
239 | | return dim(vm.toString(self));
240 | | }
241 | |
242 | | function dimBytes(bytes memory self) internal pure returns (string memory) {
243 | | return dim(vm.toString(self));
244 | | }
245 | |
246 | | function dimBytes32(bytes32 self) internal pure returns (string memory) {
247 | | return dim(vm.toString(self));
248 | | }
249 | |
250 | | function italic(string memory self) internal pure returns (string memory) {
251 | | return styleConcat(ITALIC, self);
252 | | }
253 | |
254 | | function italic(uint256 self) internal pure returns (string memory) {
255 | | return italic(vm.toString(self));
256 | | }
257 | |
258 | | function italic(int256 self) internal pure returns (string memory) {
259 | | return italic(vm.toString(self));
260 | | }
261 | |
262 | | function italic(address self) internal pure returns (string memory) {
263 | | return italic(vm.toString(self));
264 | | }
265 | |
266 | | function italic(bool self) internal pure returns (string memory) {
267 | | return italic(vm.toString(self));
268 | | }
269 | |
270 | | function italicBytes(bytes memory self) internal pure returns (string memory) {
271 | | return italic(vm.toString(self));
272 | | }
273 | |
274 | | function italicBytes32(bytes32 self) internal pure returns (string memory) {
275 | | return italic(vm.toString(self));
276 | | }
277 | |
278 | | function underline(string memory self) internal pure returns (string memory) {
279 | | return styleConcat(UNDERLINE, self);
280 | | }
281 | |
282 | | function underline(uint256 self) internal pure returns (string memory) {
283 | | return underline(vm.toString(self));
284 | | }
285 | |
286 | | function underline(int256 self) internal pure returns (string memory) {
287 | | return underline(vm.toString(self));
288 | | }
289 | |
290 | | function underline(address self) internal pure returns (string memory) {
291 | | return underline(vm.toString(self));
292 | | }
293 | |
294 | | function underline(bool self) internal pure returns (string memory) {
295 | | return underline(vm.toString(self));
296 | | }
297 | |
298 | | function underlineBytes(bytes memory self) internal pure returns (string memory) {
299 | | return underline(vm.toString(self));
300 | | }
301 | |
302 | | function underlineBytes32(bytes32 self) internal pure returns (string memory) {
303 | | return underline(vm.toString(self));
304 | | }
305 | |
306 | | function inverse(string memory self) internal pure returns (string memory) {
307 | | return styleConcat(INVERSE, self);
308 | | }
309 | |
310 | | function inverse(uint256 self) internal pure returns (string memory) {
311 | | return inverse(vm.toString(self));
312 | | }
313 | |
314 | | function inverse(int256 self) internal pure returns (string memory) {
315 | | return inverse(vm.toString(self));
316 | | }
317 | |
318 | | function inverse(address self) internal pure returns (string memory) {
319 | | return inverse(vm.toString(self));
320 | | }
321 | |
322 | | function inverse(bool self) internal pure returns (string memory) {
323 | | return inverse(vm.toString(self));
324 | | }
325 | |
326 | | function inverseBytes(bytes memory self) internal pure returns (string memory) {
327 | | return inverse(vm.toString(self));
328 | | }
329 | |
330 | | function inverseBytes32(bytes32 self) internal pure returns (string memory) {
331 | | return inverse(vm.toString(self));
332 | | }
333 | | }
334 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdToml.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.0 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | import {VmSafe} from "./Vm.sol";
7 | |
8 | | // Helpers for parsing and writing TOML files
9 | | // To parse:
10 | | // ```
11 | | // using stdToml for string;
12 | | // string memory toml = vm.readFile("<some_path>");
13 | | // toml.readUint("<json_path>");
14 | | // ```
15 | | // To write:
16 | | // ```
17 | | // using stdToml for string;
18 | | // string memory json = "json";
19 | | // json.serialize("a", uint256(123));
20 | | // string memory semiFinal = json.serialize("b", string("test"));
21 | | // string memory finalJson = json.serialize("c", semiFinal);
22 | | // finalJson.write("<some_path>");
23 | | // ```
24 | |
25 | * | library stdToml {
26 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
27 | |
28 | | function keyExists(string memory toml, string memory key) internal view returns (bool) {
29 | | return vm.keyExistsToml(toml, key);
30 | | }
31 | |
32 | | function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) {
33 | | return vm.parseToml(toml, key);
34 | | }
35 | |
36 | | function readUint(string memory toml, string memory key) internal pure returns (uint256) {
37 | | return vm.parseTomlUint(toml, key);
38 | | }
39 | |
40 | | function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) {
41 | | return vm.parseTomlUintArray(toml, key);
42 | | }
43 | |
44 | | function readInt(string memory toml, string memory key) internal pure returns (int256) {
45 | | return vm.parseTomlInt(toml, key);
46 | | }
47 | |
48 | | function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) {
49 | | return vm.parseTomlIntArray(toml, key);
50 | | }
51 | |
52 | | function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) {
53 | | return vm.parseTomlBytes32(toml, key);
54 | | }
55 | |
56 | | function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) {
57 | | return vm.parseTomlBytes32Array(toml, key);
58 | | }
59 | |
60 | | function readString(string memory toml, string memory key) internal pure returns (string memory) {
61 | | return vm.parseTomlString(toml, key);
62 | | }
63 | |
64 | | function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) {
65 | | return vm.parseTomlStringArray(toml, key);
66 | | }
67 | |
68 | | function readAddress(string memory toml, string memory key) internal pure returns (address) {
69 | | return vm.parseTomlAddress(toml, key);
70 | | }
71 | |
72 | | function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) {
73 | | return vm.parseTomlAddressArray(toml, key);
74 | | }
75 | |
76 | | function readBool(string memory toml, string memory key) internal pure returns (bool) {
77 | | return vm.parseTomlBool(toml, key);
78 | | }
79 | |
80 | | function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) {
81 | | return vm.parseTomlBoolArray(toml, key);
82 | | }
83 | |
84 | | function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) {
85 | | return vm.parseTomlBytes(toml, key);
86 | | }
87 | |
88 | | function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) {
89 | | return vm.parseTomlBytesArray(toml, key);
90 | | }
91 | |
92 | | function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) {
93 | | return keyExists(toml, key) ? readUint(toml, key) : defaultValue;
94 | | }
95 | |
96 | | function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue)
97 | | internal
98 | | view
99 | | returns (uint256[] memory)
100 | | {
101 | | return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue;
102 | | }
103 | |
104 | | function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) {
105 | | return keyExists(toml, key) ? readInt(toml, key) : defaultValue;
106 | | }
107 | |
108 | | function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue)
109 | | internal
110 | | view
111 | | returns (int256[] memory)
112 | | {
113 | | return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue;
114 | | }
115 | |
116 | | function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue)
117 | | internal
118 | | view
119 | | returns (bytes32)
120 | | {
121 | | return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue;
122 | | }
123 | |
124 | | function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue)
125 | | internal
126 | | view
127 | | returns (bytes32[] memory)
128 | | {
129 | | return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue;
130 | | }
131 | |
132 | | function readStringOr(string memory toml, string memory key, string memory defaultValue)
133 | | internal
134 | | view
135 | | returns (string memory)
136 | | {
137 | | return keyExists(toml, key) ? readString(toml, key) : defaultValue;
138 | | }
139 | |
140 | | function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue)
141 | | internal
142 | | view
143 | | returns (string[] memory)
144 | | {
145 | | return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue;
146 | | }
147 | |
148 | | function readAddressOr(string memory toml, string memory key, address defaultValue)
149 | | internal
150 | | view
151 | | returns (address)
152 | | {
153 | | return keyExists(toml, key) ? readAddress(toml, key) : defaultValue;
154 | | }
155 | |
156 | | function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue)
157 | | internal
158 | | view
159 | | returns (address[] memory)
160 | | {
161 | | return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue;
162 | | }
163 | |
164 | | function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) {
165 | | return keyExists(toml, key) ? readBool(toml, key) : defaultValue;
166 | | }
167 | |
168 | | function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue)
169 | | internal
170 | | view
171 | | returns (bool[] memory)
172 | | {
173 | | return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue;
174 | | }
175 | |
176 | | function readBytesOr(string memory toml, string memory key, bytes memory defaultValue)
177 | | internal
178 | | view
179 | | returns (bytes memory)
180 | | {
181 | | return keyExists(toml, key) ? readBytes(toml, key) : defaultValue;
182 | | }
183 | |
184 | | function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue)
185 | | internal
186 | | view
187 | | returns (bytes[] memory)
188 | | {
189 | | return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue;
190 | | }
191 | |
192 | | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
193 | | return vm.serializeJson(jsonKey, rootObject);
194 | | }
195 | |
196 | | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
197 | | return vm.serializeBool(jsonKey, key, value);
198 | | }
199 | |
200 | | function serialize(string memory jsonKey, string memory key, bool[] memory value)
201 | | internal
202 | | returns (string memory)
203 | | {
204 | | return vm.serializeBool(jsonKey, key, value);
205 | | }
206 | |
207 | | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
208 | | return vm.serializeUint(jsonKey, key, value);
209 | | }
210 | |
211 | | function serialize(string memory jsonKey, string memory key, uint256[] memory value)
212 | | internal
213 | | returns (string memory)
214 | | {
215 | | return vm.serializeUint(jsonKey, key, value);
216 | | }
217 | |
218 | | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
219 | | return vm.serializeInt(jsonKey, key, value);
220 | | }
221 | |
222 | | function serialize(string memory jsonKey, string memory key, int256[] memory value)
223 | | internal
224 | | returns (string memory)
225 | | {
226 | | return vm.serializeInt(jsonKey, key, value);
227 | | }
228 | |
229 | | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
230 | | return vm.serializeAddress(jsonKey, key, value);
231 | | }
232 | |
233 | | function serialize(string memory jsonKey, string memory key, address[] memory value)
234 | | internal
235 | | returns (string memory)
236 | | {
237 | | return vm.serializeAddress(jsonKey, key, value);
238 | | }
239 | |
240 | | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
241 | | return vm.serializeBytes32(jsonKey, key, value);
242 | | }
243 | |
244 | | function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
245 | | internal
246 | | returns (string memory)
247 | | {
248 | | return vm.serializeBytes32(jsonKey, key, value);
249 | | }
250 | |
251 | | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
252 | | return vm.serializeBytes(jsonKey, key, value);
253 | | }
254 | |
255 | | function serialize(string memory jsonKey, string memory key, bytes[] memory value)
256 | | internal
257 | | returns (string memory)
258 | | {
259 | | return vm.serializeBytes(jsonKey, key, value);
260 | | }
261 | |
262 | | function serialize(string memory jsonKey, string memory key, string memory value)
263 | | internal
264 | | returns (string memory)
265 | | {
266 | | return vm.serializeString(jsonKey, key, value);
267 | | }
268 | |
269 | | function serialize(string memory jsonKey, string memory key, string[] memory value)
270 | | internal
271 | | returns (string memory)
272 | | {
273 | | return vm.serializeString(jsonKey, key, value);
274 | | }
275 | |
276 | | function write(string memory jsonKey, string memory path) internal {
277 | | vm.writeToml(jsonKey, path);
278 | | }
279 | |
280 | | function write(string memory jsonKey, string memory path, string memory valueKey) internal {
281 | | vm.writeToml(jsonKey, path, valueKey);
282 | | }
283 | | }
284 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdUtils.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | import {IMulticall3} from "./interfaces/IMulticall3.sol";
7 | | import {MockERC20} from "./mocks/MockERC20.sol";
8 | | import {MockERC721} from "./mocks/MockERC721.sol";
9 | | import {VmSafe} from "./Vm.sol";
10 | |
11 | | abstract contract StdUtils {
12 | | /*//////////////////////////////////////////////////////////////////////////
13 | | CONSTANTS
14 | | //////////////////////////////////////////////////////////////////////////*/
15 | |
16 | | IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
17 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
18 | | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
19 | | uint256 private constant INT256_MIN_ABS =
20 | | 57896044618658097711785492504343953926634992332820282019728792003956564819968;
21 | | uint256 private constant SECP256K1_ORDER =
22 | | 115792089237316195423570985008687907852837564279074904382605163141518161494337;
23 | | uint256 private constant UINT256_MAX =
24 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935;
25 | |
26 | | // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
27 | | address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
28 | |
29 | | /*//////////////////////////////////////////////////////////////////////////
30 | | INTERNAL FUNCTIONS
31 | | //////////////////////////////////////////////////////////////////////////*/
32 | |
33 | | function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
34 | | require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
35 | | // If x is between min and max, return x directly. This is to ensure that dictionary values
36 | | // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
37 | | if (x >= min && x <= max) return x;
38 | |
39 | | uint256 size = max - min + 1;
40 | |
41 | | // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
42 | | // This helps ensure coverage of the min/max values.
43 | | if (x <= 3 && size > x) return min + x;
44 | | if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
45 | |
46 | | // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
47 | | if (x > max) {
48 | | uint256 diff = x - max;
49 | | uint256 rem = diff % size;
50 | | if (rem == 0) return max;
51 | | result = min + rem - 1;
52 | | } else if (x < min) {
53 | | uint256 diff = min - x;
54 | | uint256 rem = diff % size;
55 | | if (rem == 0) return min;
56 | | result = max - rem + 1;
57 | | }
58 | | }
59 | |
60 | | function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
61 | | result = _bound(x, min, max);
62 | | console2_log_StdUtils("Bound result", result);
63 | | }
64 | |
65 | | function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
66 | | require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
67 | |
68 | | // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
69 | | // int256 : -(2**255) ~ (2**255 - 1)
70 | | // uint256: 0 ~ (2**256 - 1)
71 | | // So, add 2**255, INT256_MIN_ABS to the integer values.
72 | | //
73 | | // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
74 | | // So, use `~uint256(x) + 1` instead.
75 | | uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
76 | | uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
77 | | uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
78 | |
79 | | uint256 y = _bound(_x, _min, _max);
80 | |
81 | | // To move it back to int256 value, subtract INT256_MIN_ABS at here.
82 | | result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
83 | | }
84 | |
85 | | function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
86 | | result = _bound(x, min, max);
87 | | console2_log_StdUtils("Bound result", vm.toString(result));
88 | | }
89 | |
90 | | function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
91 | | result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
92 | | }
93 | |
94 | | function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
95 | | require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
96 | | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
97 | | }
98 | |
99 | | /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
100 | | /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
101 | | function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
102 | | console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
103 | | return vm.computeCreateAddress(deployer, nonce);
104 | | }
105 | |
106 | | function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
107 | | internal
108 | | pure
109 | | virtual
110 | | returns (address)
111 | | {
112 | | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
113 | | return vm.computeCreate2Address(salt, initcodeHash, deployer);
114 | | }
115 | |
116 | | /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
117 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
118 | | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
119 | | return vm.computeCreate2Address(salt, initCodeHash);
120 | | }
121 | |
122 | | /// @dev returns an initialized mock ERC20 contract
123 | | function deployMockERC20(string memory name, string memory symbol, uint8 decimals)
124 | | internal
125 | | returns (MockERC20 mock)
126 | | {
127 | | mock = new MockERC20();
128 | | mock.initialize(name, symbol, decimals);
129 | | }
130 | |
131 | | /// @dev returns an initialized mock ERC721 contract
132 | | function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) {
133 | | mock = new MockERC721();
134 | | mock.initialize(name, symbol);
135 | | }
136 | |
137 | | /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
138 | | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
139 | | function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
140 | | return hashInitCode(creationCode, "");
141 | | }
142 | |
143 | | /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
144 | | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
145 | | /// @param args the ABI-encoded arguments to the constructor of C
146 | | function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
147 | | return keccak256(abi.encodePacked(creationCode, args));
148 | | }
149 | |
150 | | // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
151 | | function getTokenBalances(address token, address[] memory addresses)
152 | | internal
153 | | virtual
154 | | returns (uint256[] memory balances)
155 | | {
156 | | uint256 tokenCodeSize;
157 | | assembly {
158 | | tokenCodeSize := extcodesize(token)
159 | | }
160 | | require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
161 | |
162 | | // ABI encode the aggregate call to Multicall3.
163 | | uint256 length = addresses.length;
164 | | IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
165 | | for (uint256 i = 0; i < length; ++i) {
166 | | // 0x70a08231 = bytes4("balanceOf(address)"))
167 | | calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
168 | | }
169 | |
170 | | // Make the aggregate call.
171 | | (, bytes[] memory returnData) = multicall.aggregate(calls);
172 | |
173 | | // ABI decode the return data and return the balances.
174 | | balances = new uint256[](length);
175 | | for (uint256 i = 0; i < length; ++i) {
176 | | balances[i] = abi.decode(returnData[i], (uint256));
177 | | }
178 | | }
179 | |
180 | | /*//////////////////////////////////////////////////////////////////////////
181 | | PRIVATE FUNCTIONS
182 | | //////////////////////////////////////////////////////////////////////////*/
183 | |
184 | | function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
185 | | return address(uint160(uint256(bytesValue)));
186 | | }
187 | |
188 | | // This section is used to prevent the compilation of console, which shortens the compilation time when console is
189 | | // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
190 | | // any breaking changes to function signatures.
191 | | function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
192 | | internal
193 | | pure
194 | | returns (function(bytes memory) internal pure fnOut)
195 | | {
196 | | assembly {
197 | | fnOut := fnIn
198 | | }
199 | | }
200 | |
201 | | function _sendLogPayload(bytes memory payload) internal pure {
202 | | _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
203 | | }
204 | |
205 | | function _sendLogPayloadView(bytes memory payload) private view {
206 | | uint256 payloadLength = payload.length;
207 | | address consoleAddress = CONSOLE2_ADDRESS;
208 | | /// @solidity memory-safe-assembly
209 | | assembly {
210 | | let payloadStart := add(payload, 32)
211 | | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
212 | | }
213 | | }
214 | |
215 | | function console2_log_StdUtils(string memory p0) private pure {
216 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
217 | | }
218 | |
219 | | function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
220 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
221 | | }
222 | |
223 | | function console2_log_StdUtils(string memory p0, string memory p1) private pure {
224 | | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
225 | | }
226 | | }
227 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Test.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | // 💬 ABOUT
7 | | // Forge Std's default Test.
8 | |
9 | | // 🧩 MODULES
10 | | import {console} from "./console.sol";
11 | | import {console2} from "./console2.sol";
12 | | import {safeconsole} from "./safeconsole.sol";
13 | | import {StdAssertions} from "./StdAssertions.sol";
14 | | import {StdChains} from "./StdChains.sol";
15 | | import {StdCheats} from "./StdCheats.sol";
16 | | import {stdError} from "./StdError.sol";
17 | | import {StdInvariant} from "./StdInvariant.sol";
18 | | import {stdJson} from "./StdJson.sol";
19 | | import {stdMath} from "./StdMath.sol";
20 | | import {StdStorage, stdStorage} from "./StdStorage.sol";
21 | | import {StdStyle} from "./StdStyle.sol";
22 | | import {stdToml} from "./StdToml.sol";
23 | | import {StdUtils} from "./StdUtils.sol";
24 | | import {Vm} from "./Vm.sol";
25 | |
26 | | // 📦 BOILERPLATE
27 | | import {TestBase} from "./Base.sol";
28 | |
29 | | // ⭐️ TEST
30 | | abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils {
31 | | // Note: IS_TEST() must return true.
32 | * | bool public IS_TEST = true;
33 | | }
34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Vm.sol
1 | | // Automatically @generated by scripts/vm.py. Do not modify manually.
2 | |
3 | | // SPDX-License-Identifier: MIT OR Apache-2.0
4 | | pragma solidity >=0.6.2 <0.9.0;
5 | | pragma experimental ABIEncoderV2;
6 | |
7 | | /// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
8 | | /// result in Script simulations differing from on-chain execution. It is recommended to only use
9 | | /// these cheats in scripts.
10 | | interface VmSafe {
11 | | /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
12 | | enum CallerMode {
13 | | // No caller modification is currently active.
14 | | None,
15 | | // A one time broadcast triggered by a `vm.broadcast()` call is currently active.
16 | | Broadcast,
17 | | // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
18 | | RecurrentBroadcast,
19 | | // A one time prank triggered by a `vm.prank()` call is currently active.
20 | | Prank,
21 | | // A recurrent prank triggered by a `vm.startPrank()` call is currently active.
22 | | RecurrentPrank
23 | | }
24 | |
25 | | /// The kind of account access that occurred.
26 | | enum AccountAccessKind {
27 | | // The account was called.
28 | | Call,
29 | | // The account was called via delegatecall.
30 | | DelegateCall,
31 | | // The account was called via callcode.
32 | | CallCode,
33 | | // The account was called via staticcall.
34 | | StaticCall,
35 | | // The account was created.
36 | | Create,
37 | | // The account was selfdestructed.
38 | | SelfDestruct,
39 | | // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
40 | | Resume,
41 | | // The account's balance was read.
42 | | Balance,
43 | | // The account's codesize was read.
44 | | Extcodesize,
45 | | // The account's codehash was read.
46 | | Extcodehash,
47 | | // The account's code was copied.
48 | | Extcodecopy
49 | | }
50 | |
51 | | /// Forge execution contexts.
52 | | enum ForgeContext {
53 | | // Test group execution context (test, coverage or snapshot).
54 | | TestGroup,
55 | | // `forge test` execution context.
56 | | Test,
57 | | // `forge coverage` execution context.
58 | | Coverage,
59 | | // `forge snapshot` execution context.
60 | | Snapshot,
61 | | // Script group execution context (dry run, broadcast or resume).
62 | | ScriptGroup,
63 | | // `forge script` execution context.
64 | | ScriptDryRun,
65 | | // `forge script --broadcast` execution context.
66 | | ScriptBroadcast,
67 | | // `forge script --resume` execution context.
68 | | ScriptResume,
69 | | // Unknown `forge` execution context.
70 | | Unknown
71 | | }
72 | |
73 | | /// An Ethereum log. Returned by `getRecordedLogs`.
74 | | struct Log {
75 | | // The topics of the log, including the signature, if any.
76 | | bytes32[] topics;
77 | | // The raw data of the log.
78 | | bytes data;
79 | | // The address of the log's emitter.
80 | | address emitter;
81 | | }
82 | |
83 | | /// An RPC URL and its alias. Returned by `rpcUrlStructs`.
84 | | struct Rpc {
85 | | // The alias of the RPC URL.
86 | | string key;
87 | | // The RPC URL.
88 | | string url;
89 | | }
90 | |
91 | | /// An RPC log object. Returned by `eth_getLogs`.
92 | | struct EthGetLogs {
93 | | // The address of the log's emitter.
94 | | address emitter;
95 | | // The topics of the log, including the signature, if any.
96 | | bytes32[] topics;
97 | | // The raw data of the log.
98 | | bytes data;
99 | | // The block hash.
100 | | bytes32 blockHash;
101 | | // The block number.
102 | | uint64 blockNumber;
103 | | // The transaction hash.
104 | | bytes32 transactionHash;
105 | | // The transaction index in the block.
106 | | uint64 transactionIndex;
107 | | // The log index.
108 | | uint256 logIndex;
109 | | // Whether the log was removed.
110 | | bool removed;
111 | | }
112 | |
113 | | /// A single entry in a directory listing. Returned by `readDir`.
114 | | struct DirEntry {
115 | | // The error message, if any.
116 | | string errorMessage;
117 | | // The path of the entry.
118 | | string path;
119 | | // The depth of the entry.
120 | | uint64 depth;
121 | | // Whether the entry is a directory.
122 | | bool isDir;
123 | | // Whether the entry is a symlink.
124 | | bool isSymlink;
125 | | }
126 | |
127 | | /// Metadata information about a file.
128 | | /// This structure is returned from the `fsMetadata` function and represents known
129 | | /// metadata about a file such as its permissions, size, modification
130 | | /// times, etc.
131 | | struct FsMetadata {
132 | | // True if this metadata is for a directory.
133 | | bool isDir;
134 | | // True if this metadata is for a symlink.
135 | | bool isSymlink;
136 | | // The size of the file, in bytes, this metadata is for.
137 | | uint256 length;
138 | | // True if this metadata is for a readonly (unwritable) file.
139 | | bool readOnly;
140 | | // The last modification time listed in this metadata.
141 | | uint256 modified;
142 | | // The last access time of this metadata.
143 | | uint256 accessed;
144 | | // The creation time listed in this metadata.
145 | | uint256 created;
146 | | }
147 | |
148 | | /// A wallet with a public and private key.
149 | | struct Wallet {
150 | | // The wallet's address.
151 | | address addr;
152 | | // The wallet's public key `X`.
153 | | uint256 publicKeyX;
154 | | // The wallet's public key `Y`.
155 | | uint256 publicKeyY;
156 | | // The wallet's private key.
157 | | uint256 privateKey;
158 | | }
159 | |
160 | | /// The result of a `tryFfi` call.
161 | | struct FfiResult {
162 | | // The exit code of the call.
163 | | int32 exitCode;
164 | | // The optionally hex-decoded `stdout` data.
165 | | bytes stdout;
166 | | // The `stderr` data.
167 | | bytes stderr;
168 | | }
169 | |
170 | | /// Information on the chain and fork.
171 | | struct ChainInfo {
172 | | // The fork identifier. Set to zero if no fork is active.
173 | | uint256 forkId;
174 | | // The chain ID of the current fork.
175 | | uint256 chainId;
176 | | }
177 | |
178 | | /// The result of a `stopAndReturnStateDiff` call.
179 | | struct AccountAccess {
180 | | // The chain and fork the access occurred.
181 | | ChainInfo chainInfo;
182 | | // The kind of account access that determines what the account is.
183 | | // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
184 | | // If kind is Create, then the account is the newly created account.
185 | | // If kind is SelfDestruct, then the account is the selfdestruct recipient.
186 | | // If kind is a Resume, then account represents a account context that has resumed.
187 | | AccountAccessKind kind;
188 | | // The account that was accessed.
189 | | // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
190 | | address account;
191 | | // What accessed the account.
192 | | address accessor;
193 | | // If the account was initialized or empty prior to the access.
194 | | // An account is considered initialized if it has code, a
195 | | // non-zero nonce, or a non-zero balance.
196 | | bool initialized;
197 | | // The previous balance of the accessed account.
198 | | uint256 oldBalance;
199 | | // The potential new balance of the accessed account.
200 | | // That is, all balance changes are recorded here, even if reverts occurred.
201 | | uint256 newBalance;
202 | | // Code of the account deployed by CREATE.
203 | | bytes deployedCode;
204 | | // Value passed along with the account access
205 | | uint256 value;
206 | | // Input data provided to the CREATE or CALL
207 | | bytes data;
208 | | // If this access reverted in either the current or parent context.
209 | | bool reverted;
210 | | // An ordered list of storage accesses made during an account access operation.
211 | | StorageAccess[] storageAccesses;
212 | | // Call depth traversed during the recording of state differences
213 | | uint64 depth;
214 | | }
215 | |
216 | | /// The storage accessed during an `AccountAccess`.
217 | | struct StorageAccess {
218 | | // The account whose storage was accessed.
219 | | address account;
220 | | // The slot that was accessed.
221 | | bytes32 slot;
222 | | // If the access was a write.
223 | | bool isWrite;
224 | | // The previous value of the slot.
225 | | bytes32 previousValue;
226 | | // The new value of the slot.
227 | | bytes32 newValue;
228 | | // If the access was reverted.
229 | | bool reverted;
230 | | }
231 | |
232 | | /// Gas used. Returned by `lastCallGas`.
233 | | struct Gas {
234 | | // The gas limit of the call.
235 | | uint64 gasLimit;
236 | | // The total gas used.
237 | | uint64 gasTotalUsed;
238 | | // DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939>
239 | | uint64 gasMemoryUsed;
240 | | // The amount of gas refunded.
241 | | int64 gasRefunded;
242 | | // The amount of gas remaining.
243 | | uint64 gasRemaining;
244 | | }
245 | |
246 | | // ======== Crypto ========
247 | |
248 | | /// Derives a private key from the name, labels the account with that name, and returns the wallet.
249 | | function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
250 | |
251 | | /// Generates a wallet from the private key and returns the wallet.
252 | | function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
253 | |
254 | | /// Generates a wallet from the private key, labels the account with that name, and returns the wallet.
255 | | function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
256 | |
257 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path)
258 | | /// at the derivation path `m/44'/60'/0'/0/{index}`.
259 | | function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
260 | |
261 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path)
262 | | /// at `{derivationPath}{index}`.
263 | | function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
264 | | external
265 | | pure
266 | | returns (uint256 privateKey);
267 | |
268 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
269 | | /// at the derivation path `m/44'/60'/0'/0/{index}`.
270 | | function deriveKey(string calldata mnemonic, uint32 index, string calldata language)
271 | | external
272 | | pure
273 | | returns (uint256 privateKey);
274 | |
275 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
276 | | /// at `{derivationPath}{index}`.
277 | | function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language)
278 | | external
279 | | pure
280 | | returns (uint256 privateKey);
281 | |
282 | | /// Derives secp256r1 public key from the provided `privateKey`.
283 | | function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY);
284 | |
285 | | /// Adds a private key to the local forge wallet and returns the address.
286 | | function rememberKey(uint256 privateKey) external returns (address keyAddr);
287 | |
288 | | /// Signs data with a `Wallet`.
289 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
290 | | /// signature's `s` value, and the recovery id `v` in a single bytes32.
291 | | /// This format reduces the signature size from 65 to 64 bytes.
292 | | function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);
293 | |
294 | | /// Signs `digest` with `privateKey` using the secp256k1 curve.
295 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
296 | | /// signature's `s` value, and the recovery id `v` in a single bytes32.
297 | | /// This format reduces the signature size from 65 to 64 bytes.
298 | | function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
299 | |
300 | | /// Signs `digest` with signer provided to script using the secp256k1 curve.
301 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
302 | | /// signature's `s` value, and the recovery id `v` in a single bytes32.
303 | | /// This format reduces the signature size from 65 to 64 bytes.
304 | | /// If `--sender` is provided, the signer with provided address is used, otherwise,
305 | | /// if exactly one signer is provided to the script, that signer is used.
306 | | /// Raises error if signer passed through `--sender` does not match any unlocked signers or
307 | | /// if `--sender` is not provided and not exactly one signer is passed to the script.
308 | | function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
309 | |
310 | | /// Signs `digest` with signer provided to script using the secp256k1 curve.
311 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
312 | | /// signature's `s` value, and the recovery id `v` in a single bytes32.
313 | | /// This format reduces the signature size from 65 to 64 bytes.
314 | | /// Raises error if none of the signers passed into the script have provided address.
315 | | function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
316 | |
317 | | /// Signs `digest` with `privateKey` using the secp256r1 curve.
318 | | function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);
319 | |
320 | | /// Signs data with a `Wallet`.
321 | | function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
322 | |
323 | | /// Signs `digest` with `privateKey` using the secp256k1 curve.
324 | | function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
325 | |
326 | | /// Signs `digest` with signer provided to script using the secp256k1 curve.
327 | | /// If `--sender` is provided, the signer with provided address is used, otherwise,
328 | | /// if exactly one signer is provided to the script, that signer is used.
329 | | /// Raises error if signer passed through `--sender` does not match any unlocked signers or
330 | | /// if `--sender` is not provided and not exactly one signer is passed to the script.
331 | | function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
332 | |
333 | | /// Signs `digest` with signer provided to script using the secp256k1 curve.
334 | | /// Raises error if none of the signers passed into the script have provided address.
335 | | function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
336 | |
337 | | // ======== Environment ========
338 | |
339 | | /// Gets the environment variable `name` and parses it as `address`.
340 | | /// Reverts if the variable was not found or could not be parsed.
341 | | function envAddress(string calldata name) external view returns (address value);
342 | |
343 | | /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
344 | | /// Reverts if the variable was not found or could not be parsed.
345 | | function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
346 | |
347 | | /// Gets the environment variable `name` and parses it as `bool`.
348 | | /// Reverts if the variable was not found or could not be parsed.
349 | | function envBool(string calldata name) external view returns (bool value);
350 | |
351 | | /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
352 | | /// Reverts if the variable was not found or could not be parsed.
353 | | function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
354 | |
355 | | /// Gets the environment variable `name` and parses it as `bytes32`.
356 | | /// Reverts if the variable was not found or could not be parsed.
357 | | function envBytes32(string calldata name) external view returns (bytes32 value);
358 | |
359 | | /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
360 | | /// Reverts if the variable was not found or could not be parsed.
361 | | function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
362 | |
363 | | /// Gets the environment variable `name` and parses it as `bytes`.
364 | | /// Reverts if the variable was not found or could not be parsed.
365 | | function envBytes(string calldata name) external view returns (bytes memory value);
366 | |
367 | | /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
368 | | /// Reverts if the variable was not found or could not be parsed.
369 | | function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
370 | |
371 | | /// Gets the environment variable `name` and returns true if it exists, else returns false.
372 | | function envExists(string calldata name) external view returns (bool result);
373 | |
374 | | /// Gets the environment variable `name` and parses it as `int256`.
375 | | /// Reverts if the variable was not found or could not be parsed.
376 | | function envInt(string calldata name) external view returns (int256 value);
377 | |
378 | | /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
379 | | /// Reverts if the variable was not found or could not be parsed.
380 | | function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
381 | |
382 | | /// Gets the environment variable `name` and parses it as `bool`.
383 | | /// Reverts if the variable could not be parsed.
384 | | /// Returns `defaultValue` if the variable was not found.
385 | | function envOr(string calldata name, bool defaultValue) external view returns (bool value);
386 | |
387 | | /// Gets the environment variable `name` and parses it as `uint256`.
388 | | /// Reverts if the variable could not be parsed.
389 | | /// Returns `defaultValue` if the variable was not found.
390 | | function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);
391 | |
392 | | /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
393 | | /// Reverts if the variable could not be parsed.
394 | | /// Returns `defaultValue` if the variable was not found.
395 | | function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
396 | | external
397 | | view
398 | | returns (address[] memory value);
399 | |
400 | | /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
401 | | /// Reverts if the variable could not be parsed.
402 | | /// Returns `defaultValue` if the variable was not found.
403 | | function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
404 | | external
405 | | view
406 | | returns (bytes32[] memory value);
407 | |
408 | | /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
409 | | /// Reverts if the variable could not be parsed.
410 | | /// Returns `defaultValue` if the variable was not found.
411 | | function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
412 | | external
413 | | view
414 | | returns (string[] memory value);
415 | |
416 | | /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
417 | | /// Reverts if the variable could not be parsed.
418 | | /// Returns `defaultValue` if the variable was not found.
419 | | function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
420 | | external
421 | | view
422 | | returns (bytes[] memory value);
423 | |
424 | | /// Gets the environment variable `name` and parses it as `int256`.
425 | | /// Reverts if the variable could not be parsed.
426 | | /// Returns `defaultValue` if the variable was not found.
427 | | function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);
428 | |
429 | | /// Gets the environment variable `name` and parses it as `address`.
430 | | /// Reverts if the variable could not be parsed.
431 | | /// Returns `defaultValue` if the variable was not found.
432 | | function envOr(string calldata name, address defaultValue) external view returns (address value);
433 | |
434 | | /// Gets the environment variable `name` and parses it as `bytes32`.
435 | | /// Reverts if the variable could not be parsed.
436 | | /// Returns `defaultValue` if the variable was not found.
437 | | function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);
438 | |
439 | | /// Gets the environment variable `name` and parses it as `string`.
440 | | /// Reverts if the variable could not be parsed.
441 | | /// Returns `defaultValue` if the variable was not found.
442 | | function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);
443 | |
444 | | /// Gets the environment variable `name` and parses it as `bytes`.
445 | | /// Reverts if the variable could not be parsed.
446 | | /// Returns `defaultValue` if the variable was not found.
447 | | function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);
448 | |
449 | | /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
450 | | /// Reverts if the variable could not be parsed.
451 | | /// Returns `defaultValue` if the variable was not found.
452 | | function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
453 | | external
454 | | view
455 | | returns (bool[] memory value);
456 | |
457 | | /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
458 | | /// Reverts if the variable could not be parsed.
459 | | /// Returns `defaultValue` if the variable was not found.
460 | | function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
461 | | external
462 | | view
463 | | returns (uint256[] memory value);
464 | |
465 | | /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
466 | | /// Reverts if the variable could not be parsed.
467 | | /// Returns `defaultValue` if the variable was not found.
468 | | function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
469 | | external
470 | | view
471 | | returns (int256[] memory value);
472 | |
473 | | /// Gets the environment variable `name` and parses it as `string`.
474 | | /// Reverts if the variable was not found or could not be parsed.
475 | | function envString(string calldata name) external view returns (string memory value);
476 | |
477 | | /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
478 | | /// Reverts if the variable was not found or could not be parsed.
479 | | function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
480 | |
481 | | /// Gets the environment variable `name` and parses it as `uint256`.
482 | | /// Reverts if the variable was not found or could not be parsed.
483 | | function envUint(string calldata name) external view returns (uint256 value);
484 | |
485 | | /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
486 | | /// Reverts if the variable was not found or could not be parsed.
487 | | function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
488 | |
489 | | /// Returns true if `forge` command was executed in given context.
490 | | function isContext(ForgeContext context) external view returns (bool result);
491 | |
492 | | /// Sets environment variables.
493 | | function setEnv(string calldata name, string calldata value) external;
494 | |
495 | | // ======== EVM ========
496 | |
497 | | /// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
498 | | function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
499 | |
500 | | /// Gets the address for a given private key.
501 | | function addr(uint256 privateKey) external pure returns (address keyAddr);
502 | |
503 | | /// Gets all the logs according to specified filter.
504 | | function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
505 | | external
506 | | returns (EthGetLogs[] memory logs);
507 | |
508 | | /// Gets the current `block.blobbasefee`.
509 | | /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
510 | | /// and as a result will get optimized out by the compiler.
511 | | /// See https://github.com/foundry-rs/foundry/issues/6180
512 | | function getBlobBaseFee() external view returns (uint256 blobBaseFee);
513 | |
514 | | /// Gets the current `block.number`.
515 | | /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
516 | | /// and as a result will get optimized out by the compiler.
517 | | /// See https://github.com/foundry-rs/foundry/issues/6180
518 | | function getBlockNumber() external view returns (uint256 height);
519 | |
520 | | /// Gets the current `block.timestamp`.
521 | | /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
522 | | /// and as a result will get optimized out by the compiler.
523 | | /// See https://github.com/foundry-rs/foundry/issues/6180
524 | | function getBlockTimestamp() external view returns (uint256 timestamp);
525 | |
526 | | /// Gets the map key and parent of a mapping at a given slot, for a given address.
527 | | function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
528 | | external
529 | | returns (bool found, bytes32 key, bytes32 parent);
530 | |
531 | | /// Gets the number of elements in the mapping at the given slot, for a given address.
532 | | function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length);
533 | |
534 | | /// Gets the elements at index idx of the mapping at the given slot, for a given address. The
535 | | /// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
536 | | function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value);
537 | |
538 | | /// Gets the nonce of an account.
539 | | function getNonce(address account) external view returns (uint64 nonce);
540 | |
541 | | /// Get the nonce of a `Wallet`.
542 | | function getNonce(Wallet calldata wallet) external returns (uint64 nonce);
543 | |
544 | | /// Gets all the recorded logs.
545 | | function getRecordedLogs() external returns (Log[] memory logs);
546 | |
547 | | /// Gets the gas used in the last call.
548 | | function lastCallGas() external view returns (Gas memory gas);
549 | |
550 | | /// Loads a storage slot from an address.
551 | | function load(address target, bytes32 slot) external view returns (bytes32 data);
552 | |
553 | | /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
554 | | function pauseGasMetering() external;
555 | |
556 | | /// Records all storage reads and writes.
557 | | function record() external;
558 | |
559 | | /// Record all the transaction logs.
560 | | function recordLogs() external;
561 | |
562 | | /// Reset gas metering (i.e. gas usage is set to gas limit).
563 | | function resetGasMetering() external;
564 | |
565 | | /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
566 | | function resumeGasMetering() external;
567 | |
568 | | /// Performs an Ethereum JSON-RPC request to the current fork URL.
569 | | function rpc(string calldata method, string calldata params) external returns (bytes memory data);
570 | |
571 | | /// Performs an Ethereum JSON-RPC request to the given endpoint.
572 | | function rpc(string calldata urlOrAlias, string calldata method, string calldata params)
573 | | external
574 | | returns (bytes memory data);
575 | |
576 | | /// Starts recording all map SSTOREs for later retrieval.
577 | | function startMappingRecording() external;
578 | |
579 | | /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
580 | | /// along with the context of the calls
581 | | function startStateDiffRecording() external;
582 | |
583 | | /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
584 | | function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
585 | |
586 | | /// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
587 | | function stopMappingRecording() external;
588 | |
589 | | // ======== Filesystem ========
590 | |
591 | | /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
592 | | /// `path` is relative to the project root.
593 | | function closeFile(string calldata path) external;
594 | |
595 | | /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
596 | | /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
597 | | /// Both `from` and `to` are relative to the project root.
598 | | function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
599 | |
600 | | /// Creates a new, empty directory at the provided path.
601 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases:
602 | | /// - User lacks permissions to modify `path`.
603 | | /// - A parent of the given path doesn't exist and `recursive` is false.
604 | | /// - `path` already exists and `recursive` is false.
605 | | /// `path` is relative to the project root.
606 | | function createDir(string calldata path, bool recursive) external;
607 | |
608 | | /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
609 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
610 | | function deployCode(string calldata artifactPath) external returns (address deployedAddress);
611 | |
612 | | /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
613 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
614 | | /// Additionally accepts abi-encoded constructor arguments.
615 | | function deployCode(string calldata artifactPath, bytes calldata constructorArgs)
616 | | external
617 | | returns (address deployedAddress);
618 | |
619 | | /// Returns true if the given path points to an existing entity, else returns false.
620 | | function exists(string calldata path) external returns (bool result);
621 | |
622 | | /// Performs a foreign function call via the terminal.
623 | | function ffi(string[] calldata commandInput) external returns (bytes memory result);
624 | |
625 | | /// Given a path, query the file system to get information about a file, directory, etc.
626 | | function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
627 | |
628 | | /// Gets the artifact path from code (aka. creation code).
629 | | function getArtifactPathByCode(bytes calldata code) external view returns (string memory path);
630 | |
631 | | /// Gets the artifact path from deployed code (aka. runtime code).
632 | | function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path);
633 | |
634 | | /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
635 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
636 | | function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
637 | |
638 | | /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the
639 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
640 | | function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
641 | |
642 | | /// Returns true if the path exists on disk and is pointing at a directory, else returns false.
643 | | function isDir(string calldata path) external returns (bool result);
644 | |
645 | | /// Returns true if the path exists on disk and is pointing at a regular file, else returns false.
646 | | function isFile(string calldata path) external returns (bool result);
647 | |
648 | | /// Get the path of the current project root.
649 | | function projectRoot() external view returns (string memory path);
650 | |
651 | | /// Prompts the user for a string value in the terminal.
652 | | function prompt(string calldata promptText) external returns (string memory input);
653 | |
654 | | /// Prompts the user for an address in the terminal.
655 | | function promptAddress(string calldata promptText) external returns (address);
656 | |
657 | | /// Prompts the user for a hidden string value in the terminal.
658 | | function promptSecret(string calldata promptText) external returns (string memory input);
659 | |
660 | | /// Prompts the user for hidden uint256 in the terminal (usually pk).
661 | | function promptSecretUint(string calldata promptText) external returns (uint256);
662 | |
663 | | /// Prompts the user for uint256 in the terminal.
664 | | function promptUint(string calldata promptText) external returns (uint256);
665 | |
666 | | /// Reads the directory at the given path recursively, up to `maxDepth`.
667 | | /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned.
668 | | /// Follows symbolic links if `followLinks` is true.
669 | | function readDir(string calldata path) external view returns (DirEntry[] memory entries);
670 | |
671 | | /// See `readDir(string)`.
672 | | function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
673 | |
674 | | /// See `readDir(string)`.
675 | | function readDir(string calldata path, uint64 maxDepth, bool followLinks)
676 | | external
677 | | view
678 | | returns (DirEntry[] memory entries);
679 | |
680 | | /// Reads the entire content of file to string. `path` is relative to the project root.
681 | | function readFile(string calldata path) external view returns (string memory data);
682 | |
683 | | /// Reads the entire content of file as binary. `path` is relative to the project root.
684 | | function readFileBinary(string calldata path) external view returns (bytes memory data);
685 | |
686 | | /// Reads next line of file to string.
687 | | function readLine(string calldata path) external view returns (string memory line);
688 | |
689 | | /// Reads a symbolic link, returning the path that the link points to.
690 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases:
691 | | /// - `path` is not a symbolic link.
692 | | /// - `path` does not exist.
693 | | function readLink(string calldata linkPath) external view returns (string memory targetPath);
694 | |
695 | | /// Removes a directory at the provided path.
696 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases:
697 | | /// - `path` doesn't exist.
698 | | /// - `path` isn't a directory.
699 | | /// - User lacks permissions to modify `path`.
700 | | /// - The directory is not empty and `recursive` is false.
701 | | /// `path` is relative to the project root.
702 | | function removeDir(string calldata path, bool recursive) external;
703 | |
704 | | /// Removes a file from the filesystem.
705 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases:
706 | | /// - `path` points to a directory.
707 | | /// - The file doesn't exist.
708 | | /// - The user lacks permissions to remove the file.
709 | | /// `path` is relative to the project root.
710 | | function removeFile(string calldata path) external;
711 | |
712 | | /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.
713 | | function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
714 | |
715 | | /// Returns the time since unix epoch in milliseconds.
716 | | function unixTime() external returns (uint256 milliseconds);
717 | |
718 | | /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
719 | | /// `path` is relative to the project root.
720 | | function writeFile(string calldata path, string calldata data) external;
721 | |
722 | | /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
723 | | /// `path` is relative to the project root.
724 | | function writeFileBinary(string calldata path, bytes calldata data) external;
725 | |
726 | | /// Writes line to file, creating a file if it does not exist.
727 | | /// `path` is relative to the project root.
728 | | function writeLine(string calldata path, string calldata data) external;
729 | |
730 | | // ======== JSON ========
731 | |
732 | | /// Checks if `key` exists in a JSON object.
733 | | function keyExistsJson(string calldata json, string calldata key) external view returns (bool);
734 | |
735 | | /// Parses a string of JSON data at `key` and coerces it to `address`.
736 | | function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
737 | |
738 | | /// Parses a string of JSON data at `key` and coerces it to `address[]`.
739 | | function parseJsonAddressArray(string calldata json, string calldata key)
740 | | external
741 | | pure
742 | | returns (address[] memory);
743 | |
744 | | /// Parses a string of JSON data at `key` and coerces it to `bool`.
745 | | function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
746 | |
747 | | /// Parses a string of JSON data at `key` and coerces it to `bool[]`.
748 | | function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
749 | |
750 | | /// Parses a string of JSON data at `key` and coerces it to `bytes`.
751 | | function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
752 | |
753 | | /// Parses a string of JSON data at `key` and coerces it to `bytes32`.
754 | | function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
755 | |
756 | | /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
757 | | function parseJsonBytes32Array(string calldata json, string calldata key)
758 | | external
759 | | pure
760 | | returns (bytes32[] memory);
761 | |
762 | | /// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
763 | | function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
764 | |
765 | | /// Parses a string of JSON data at `key` and coerces it to `int256`.
766 | | function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
767 | |
768 | | /// Parses a string of JSON data at `key` and coerces it to `int256[]`.
769 | | function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
770 | |
771 | | /// Returns an array of all the keys in a JSON object.
772 | | function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
773 | |
774 | | /// Parses a string of JSON data at `key` and coerces it to `string`.
775 | | function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
776 | |
777 | | /// Parses a string of JSON data at `key` and coerces it to `string[]`.
778 | | function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
779 | |
780 | | /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`.
781 | | function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription)
782 | | external
783 | | pure
784 | | returns (bytes memory);
785 | |
786 | | /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`.
787 | | function parseJsonType(string calldata json, string calldata typeDescription)
788 | | external
789 | | pure
790 | | returns (bytes memory);
791 | |
792 | | /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`.
793 | | function parseJsonType(string calldata json, string calldata key, string calldata typeDescription)
794 | | external
795 | | pure
796 | | returns (bytes memory);
797 | |
798 | | /// Parses a string of JSON data at `key` and coerces it to `uint256`.
799 | | function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
800 | |
801 | | /// Parses a string of JSON data at `key` and coerces it to `uint256[]`.
802 | | function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
803 | |
804 | | /// ABI-encodes a JSON object.
805 | | function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);
806 | |
807 | | /// ABI-encodes a JSON object at `key`.
808 | | function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
809 | |
810 | | /// See `serializeJson`.
811 | | function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
812 | | external
813 | | returns (string memory json);
814 | |
815 | | /// See `serializeJson`.
816 | | function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
817 | | external
818 | | returns (string memory json);
819 | |
820 | | /// See `serializeJson`.
821 | | function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
822 | | external
823 | | returns (string memory json);
824 | |
825 | | /// See `serializeJson`.
826 | | function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
827 | | external
828 | | returns (string memory json);
829 | |
830 | | /// See `serializeJson`.
831 | | function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
832 | | external
833 | | returns (string memory json);
834 | |
835 | | /// See `serializeJson`.
836 | | function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
837 | | external
838 | | returns (string memory json);
839 | |
840 | | /// See `serializeJson`.
841 | | function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
842 | | external
843 | | returns (string memory json);
844 | |
845 | | /// See `serializeJson`.
846 | | function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
847 | | external
848 | | returns (string memory json);
849 | |
850 | | /// See `serializeJson`.
851 | | function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
852 | | external
853 | | returns (string memory json);
854 | |
855 | | /// See `serializeJson`.
856 | | function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
857 | | external
858 | | returns (string memory json);
859 | |
860 | | /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file.
861 | | /// Returns the stringified version of the specific JSON file up to that moment.
862 | | function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
863 | |
864 | | /// See `serializeJson`.
865 | | function serializeJsonType(string calldata typeDescription, bytes calldata value)
866 | | external
867 | | pure
868 | | returns (string memory json);
869 | |
870 | | /// See `serializeJson`.
871 | | function serializeJsonType(
872 | | string calldata objectKey,
873 | | string calldata valueKey,
874 | | string calldata typeDescription,
875 | | bytes calldata value
876 | | ) external returns (string memory json);
877 | |
878 | | /// See `serializeJson`.
879 | | function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
880 | | external
881 | | returns (string memory json);
882 | |
883 | | /// See `serializeJson`.
884 | | function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
885 | | external
886 | | returns (string memory json);
887 | |
888 | | /// See `serializeJson`.
889 | | function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value)
890 | | external
891 | | returns (string memory json);
892 | |
893 | | /// See `serializeJson`.
894 | | function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
895 | | external
896 | | returns (string memory json);
897 | |
898 | | /// See `serializeJson`.
899 | | function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
900 | | external
901 | | returns (string memory json);
902 | |
903 | | /// Write a serialized JSON object to a file. If the file exists, it will be overwritten.
904 | | function writeJson(string calldata json, string calldata path) external;
905 | |
906 | | /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.>
907 | | /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing.
908 | | function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
909 | |
910 | | /// Checks if `key` exists in a JSON object
911 | | /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.
912 | | function keyExists(string calldata json, string calldata key) external view returns (bool);
913 | |
914 | | // ======== Scripting ========
915 | |
916 | | /// Takes a signed transaction and broadcasts it to the network.
917 | | function broadcastRawTransaction(bytes calldata data) external;
918 | |
919 | | /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain.
920 | | /// Broadcasting address is determined by checking the following in order:
921 | | /// 1. If `--sender` argument was provided, that address is used.
922 | | /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
923 | | /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
924 | | function broadcast() external;
925 | |
926 | | /// Has the next call (at this call depth only) create a transaction with the address provided
927 | | /// as the sender that can later be signed and sent onchain.
928 | | function broadcast(address signer) external;
929 | |
930 | | /// Has the next call (at this call depth only) create a transaction with the private key
931 | | /// provided as the sender that can later be signed and sent onchain.
932 | | function broadcast(uint256 privateKey) external;
933 | |
934 | | /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.
935 | | /// Broadcasting address is determined by checking the following in order:
936 | | /// 1. If `--sender` argument was provided, that address is used.
937 | | /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
938 | | /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
939 | | function startBroadcast() external;
940 | |
941 | | /// Has all subsequent calls (at this call depth only) create transactions with the address
942 | | /// provided that can later be signed and sent onchain.
943 | | function startBroadcast(address signer) external;
944 | |
945 | | /// Has all subsequent calls (at this call depth only) create transactions with the private key
946 | | /// provided that can later be signed and sent onchain.
947 | | function startBroadcast(uint256 privateKey) external;
948 | |
949 | | /// Stops collecting onchain transactions.
950 | | function stopBroadcast() external;
951 | |
952 | | // ======== String ========
953 | |
954 | | /// Returns the index of the first occurrence of a `key` in an `input` string.
955 | | /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found.
956 | | /// Returns 0 in case of an empty `key`.
957 | | function indexOf(string calldata input, string calldata key) external pure returns (uint256);
958 | |
959 | | /// Parses the given `string` into an `address`.
960 | | function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
961 | |
962 | | /// Parses the given `string` into a `bool`.
963 | | function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
964 | |
965 | | /// Parses the given `string` into `bytes`.
966 | | function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
967 | |
968 | | /// Parses the given `string` into a `bytes32`.
969 | | function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
970 | |
971 | | /// Parses the given `string` into a `int256`.
972 | | function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
973 | |
974 | | /// Parses the given `string` into a `uint256`.
975 | | function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
976 | |
977 | | /// Replaces occurrences of `from` in the given `string` with `to`.
978 | | function replace(string calldata input, string calldata from, string calldata to)
979 | | external
980 | | pure
981 | | returns (string memory output);
982 | |
983 | | /// Splits the given `string` into an array of strings divided by the `delimiter`.
984 | | function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs);
985 | |
986 | | /// Converts the given `string` value to Lowercase.
987 | | function toLowercase(string calldata input) external pure returns (string memory output);
988 | |
989 | | /// Converts the given value to a `string`.
990 | | function toString(address value) external pure returns (string memory stringifiedValue);
991 | |
992 | | /// Converts the given value to a `string`.
993 | | function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
994 | |
995 | | /// Converts the given value to a `string`.
996 | | function toString(bytes32 value) external pure returns (string memory stringifiedValue);
997 | |
998 | | /// Converts the given value to a `string`.
999 | | function toString(bool value) external pure returns (string memory stringifiedValue);
1000 | |
1001 | | /// Converts the given value to a `string`.
1002 | | function toString(uint256 value) external pure returns (string memory stringifiedValue);
1003 | |
1004 | | /// Converts the given value to a `string`.
1005 | | function toString(int256 value) external pure returns (string memory stringifiedValue);
1006 | |
1007 | | /// Converts the given `string` value to Uppercase.
1008 | | function toUppercase(string calldata input) external pure returns (string memory output);
1009 | |
1010 | | /// Trims leading and trailing whitespace from the given `string` value.
1011 | | function trim(string calldata input) external pure returns (string memory output);
1012 | |
1013 | | // ======== Testing ========
1014 | |
1015 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1016 | | /// Formats values with decimals in failure message.
1017 | | function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure;
1018 | |
1019 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1020 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1021 | | function assertApproxEqAbsDecimal(
1022 | | uint256 left,
1023 | | uint256 right,
1024 | | uint256 maxDelta,
1025 | | uint256 decimals,
1026 | | string calldata error
1027 | | ) external pure;
1028 | |
1029 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1030 | | /// Formats values with decimals in failure message.
1031 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure;
1032 | |
1033 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1034 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1035 | | function assertApproxEqAbsDecimal(
1036 | | int256 left,
1037 | | int256 right,
1038 | | uint256 maxDelta,
1039 | | uint256 decimals,
1040 | | string calldata error
1041 | | ) external pure;
1042 | |
1043 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1044 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure;
1045 | |
1046 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1047 | | /// Includes error message into revert string on failure.
1048 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;
1049 | |
1050 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1051 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure;
1052 | |
1053 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1054 | | /// Includes error message into revert string on failure.
1055 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;
1056 | |
1057 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1058 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1059 | | /// Formats values with decimals in failure message.
1060 | | function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
1061 | | external
1062 | | pure;
1063 | |
1064 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1065 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1066 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1067 | | function assertApproxEqRelDecimal(
1068 | | uint256 left,
1069 | | uint256 right,
1070 | | uint256 maxPercentDelta,
1071 | | uint256 decimals,
1072 | | string calldata error
1073 | | ) external pure;
1074 | |
1075 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1076 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1077 | | /// Formats values with decimals in failure message.
1078 | | function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
1079 | | external
1080 | | pure;
1081 | |
1082 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1083 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1084 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1085 | | function assertApproxEqRelDecimal(
1086 | | int256 left,
1087 | | int256 right,
1088 | | uint256 maxPercentDelta,
1089 | | uint256 decimals,
1090 | | string calldata error
1091 | | ) external pure;
1092 | |
1093 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1094 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1095 | | function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure;
1096 | |
1097 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1098 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1099 | | /// Includes error message into revert string on failure.
1100 | | function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error)
1101 | | external
1102 | | pure;
1103 | |
1104 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1105 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1106 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure;
1107 | |
1108 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1109 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1110 | | /// Includes error message into revert string on failure.
1111 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error)
1112 | | external
1113 | | pure;
1114 | |
1115 | | /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
1116 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1117 | |
1118 | | /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
1119 | | /// Includes error message into revert string on failure.
1120 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1121 | |
1122 | | /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
1123 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
1124 | |
1125 | | /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
1126 | | /// Includes error message into revert string on failure.
1127 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1128 | |
1129 | | /// Asserts that two `bool` values are equal.
1130 | | function assertEq(bool left, bool right) external pure;
1131 | |
1132 | | /// Asserts that two `bool` values are equal and includes error message into revert string on failure.
1133 | | function assertEq(bool left, bool right, string calldata error) external pure;
1134 | |
1135 | | /// Asserts that two `string` values are equal.
1136 | | function assertEq(string calldata left, string calldata right) external pure;
1137 | |
1138 | | /// Asserts that two `string` values are equal and includes error message into revert string on failure.
1139 | | function assertEq(string calldata left, string calldata right, string calldata error) external pure;
1140 | |
1141 | | /// Asserts that two `bytes` values are equal.
1142 | | function assertEq(bytes calldata left, bytes calldata right) external pure;
1143 | |
1144 | | /// Asserts that two `bytes` values are equal and includes error message into revert string on failure.
1145 | | function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
1146 | |
1147 | | /// Asserts that two arrays of `bool` values are equal.
1148 | | function assertEq(bool[] calldata left, bool[] calldata right) external pure;
1149 | |
1150 | | /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.
1151 | | function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
1152 | |
1153 | | /// Asserts that two arrays of `uint256 values are equal.
1154 | | function assertEq(uint256[] calldata left, uint256[] calldata right) external pure;
1155 | |
1156 | | /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.
1157 | | function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
1158 | |
1159 | | /// Asserts that two arrays of `int256` values are equal.
1160 | | function assertEq(int256[] calldata left, int256[] calldata right) external pure;
1161 | |
1162 | | /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.
1163 | | function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
1164 | |
1165 | | /// Asserts that two `uint256` values are equal.
1166 | | function assertEq(uint256 left, uint256 right) external pure;
1167 | |
1168 | | /// Asserts that two arrays of `address` values are equal.
1169 | | function assertEq(address[] calldata left, address[] calldata right) external pure;
1170 | |
1171 | | /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.
1172 | | function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
1173 | |
1174 | | /// Asserts that two arrays of `bytes32` values are equal.
1175 | | function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
1176 | |
1177 | | /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.
1178 | | function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
1179 | |
1180 | | /// Asserts that two arrays of `string` values are equal.
1181 | | function assertEq(string[] calldata left, string[] calldata right) external pure;
1182 | |
1183 | | /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.
1184 | | function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
1185 | |
1186 | | /// Asserts that two arrays of `bytes` values are equal.
1187 | | function assertEq(bytes[] calldata left, bytes[] calldata right) external pure;
1188 | |
1189 | | /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.
1190 | | function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
1191 | |
1192 | | /// Asserts that two `uint256` values are equal and includes error message into revert string on failure.
1193 | | function assertEq(uint256 left, uint256 right, string calldata error) external pure;
1194 | |
1195 | | /// Asserts that two `int256` values are equal.
1196 | | function assertEq(int256 left, int256 right) external pure;
1197 | |
1198 | | /// Asserts that two `int256` values are equal and includes error message into revert string on failure.
1199 | | function assertEq(int256 left, int256 right, string calldata error) external pure;
1200 | |
1201 | | /// Asserts that two `address` values are equal.
1202 | | function assertEq(address left, address right) external pure;
1203 | |
1204 | | /// Asserts that two `address` values are equal and includes error message into revert string on failure.
1205 | | function assertEq(address left, address right, string calldata error) external pure;
1206 | |
1207 | | /// Asserts that two `bytes32` values are equal.
1208 | | function assertEq(bytes32 left, bytes32 right) external pure;
1209 | |
1210 | | /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.
1211 | | function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;
1212 | |
1213 | | /// Asserts that the given condition is false.
1214 | | function assertFalse(bool condition) external pure;
1215 | |
1216 | | /// Asserts that the given condition is false and includes error message into revert string on failure.
1217 | | function assertFalse(bool condition, string calldata error) external pure;
1218 | |
1219 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1220 | | /// Formats values with decimals in failure message.
1221 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1222 | |
1223 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1224 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1225 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1226 | |
1227 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1228 | | /// Formats values with decimals in failure message.
1229 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure;
1230 | |
1231 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1232 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1233 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1234 | |
1235 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1236 | | function assertGe(uint256 left, uint256 right) external pure;
1237 | |
1238 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1239 | | /// Includes error message into revert string on failure.
1240 | | function assertGe(uint256 left, uint256 right, string calldata error) external pure;
1241 | |
1242 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1243 | | function assertGe(int256 left, int256 right) external pure;
1244 | |
1245 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1246 | | /// Includes error message into revert string on failure.
1247 | | function assertGe(int256 left, int256 right, string calldata error) external pure;
1248 | |
1249 | | /// Compares two `uint256` values. Expects first value to be greater than second.
1250 | | /// Formats values with decimals in failure message.
1251 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1252 | |
1253 | | /// Compares two `uint256` values. Expects first value to be greater than second.
1254 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1255 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1256 | |
1257 | | /// Compares two `int256` values. Expects first value to be greater than second.
1258 | | /// Formats values with decimals in failure message.
1259 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure;
1260 | |
1261 | | /// Compares two `int256` values. Expects first value to be greater than second.
1262 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1263 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1264 | |
1265 | | /// Compares two `uint256` values. Expects first value to be greater than second.
1266 | | function assertGt(uint256 left, uint256 right) external pure;
1267 | |
1268 | | /// Compares two `uint256` values. Expects first value to be greater than second.
1269 | | /// Includes error message into revert string on failure.
1270 | | function assertGt(uint256 left, uint256 right, string calldata error) external pure;
1271 | |
1272 | | /// Compares two `int256` values. Expects first value to be greater than second.
1273 | | function assertGt(int256 left, int256 right) external pure;
1274 | |
1275 | | /// Compares two `int256` values. Expects first value to be greater than second.
1276 | | /// Includes error message into revert string on failure.
1277 | | function assertGt(int256 left, int256 right, string calldata error) external pure;
1278 | |
1279 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1280 | | /// Formats values with decimals in failure message.
1281 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1282 | |
1283 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1284 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1285 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1286 | |
1287 | | /// Compares two `int256` values. Expects first value to be less than or equal to second.
1288 | | /// Formats values with decimals in failure message.
1289 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure;
1290 | |
1291 | | /// Compares two `int256` values. Expects first value to be less than or equal to second.
1292 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1293 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1294 | |
1295 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1296 | | function assertLe(uint256 left, uint256 right) external pure;
1297 | |
1298 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1299 | | /// Includes error message into revert string on failure.
1300 | | function assertLe(uint256 left, uint256 right, string calldata error) external pure;
1301 | |
1302 | | /// Compares two `int256` values. Expects first value to be less than or equal to second.
1303 | | function assertLe(int256 left, int256 right) external pure;
1304 | |
1305 | | /// Compares two `int256` values. Expects first value to be less than or equal to second.
1306 | | /// Includes error message into revert string on failure.
1307 | | function assertLe(int256 left, int256 right, string calldata error) external pure;
1308 | |
1309 | | /// Compares two `uint256` values. Expects first value to be less than second.
1310 | | /// Formats values with decimals in failure message.
1311 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1312 | |
1313 | | /// Compares two `uint256` values. Expects first value to be less than second.
1314 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1315 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1316 | |
1317 | | /// Compares two `int256` values. Expects first value to be less than second.
1318 | | /// Formats values with decimals in failure message.
1319 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure;
1320 | |
1321 | | /// Compares two `int256` values. Expects first value to be less than second.
1322 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1323 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1324 | |
1325 | | /// Compares two `uint256` values. Expects first value to be less than second.
1326 | | function assertLt(uint256 left, uint256 right) external pure;
1327 | |
1328 | | /// Compares two `uint256` values. Expects first value to be less than second.
1329 | | /// Includes error message into revert string on failure.
1330 | | function assertLt(uint256 left, uint256 right, string calldata error) external pure;
1331 | |
1332 | | /// Compares two `int256` values. Expects first value to be less than second.
1333 | | function assertLt(int256 left, int256 right) external pure;
1334 | |
1335 | | /// Compares two `int256` values. Expects first value to be less than second.
1336 | | /// Includes error message into revert string on failure.
1337 | | function assertLt(int256 left, int256 right, string calldata error) external pure;
1338 | |
1339 | | /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
1340 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1341 | |
1342 | | /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
1343 | | /// Includes error message into revert string on failure.
1344 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1345 | |
1346 | | /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
1347 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
1348 | |
1349 | | /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
1350 | | /// Includes error message into revert string on failure.
1351 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1352 | |
1353 | | /// Asserts that two `bool` values are not equal.
1354 | | function assertNotEq(bool left, bool right) external pure;
1355 | |
1356 | | /// Asserts that two `bool` values are not equal and includes error message into revert string on failure.
1357 | | function assertNotEq(bool left, bool right, string calldata error) external pure;
1358 | |
1359 | | /// Asserts that two `string` values are not equal.
1360 | | function assertNotEq(string calldata left, string calldata right) external pure;
1361 | |
1362 | | /// Asserts that two `string` values are not equal and includes error message into revert string on failure.
1363 | | function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;
1364 | |
1365 | | /// Asserts that two `bytes` values are not equal.
1366 | | function assertNotEq(bytes calldata left, bytes calldata right) external pure;
1367 | |
1368 | | /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.
1369 | | function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
1370 | |
1371 | | /// Asserts that two arrays of `bool` values are not equal.
1372 | | function assertNotEq(bool[] calldata left, bool[] calldata right) external pure;
1373 | |
1374 | | /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.
1375 | | function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
1376 | |
1377 | | /// Asserts that two arrays of `uint256` values are not equal.
1378 | | function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure;
1379 | |
1380 | | /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.
1381 | | function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
1382 | |
1383 | | /// Asserts that two arrays of `int256` values are not equal.
1384 | | function assertNotEq(int256[] calldata left, int256[] calldata right) external pure;
1385 | |
1386 | | /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.
1387 | | function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
1388 | |
1389 | | /// Asserts that two `uint256` values are not equal.
1390 | | function assertNotEq(uint256 left, uint256 right) external pure;
1391 | |
1392 | | /// Asserts that two arrays of `address` values are not equal.
1393 | | function assertNotEq(address[] calldata left, address[] calldata right) external pure;
1394 | |
1395 | | /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.
1396 | | function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
1397 | |
1398 | | /// Asserts that two arrays of `bytes32` values are not equal.
1399 | | function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
1400 | |
1401 | | /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.
1402 | | function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
1403 | |
1404 | | /// Asserts that two arrays of `string` values are not equal.
1405 | | function assertNotEq(string[] calldata left, string[] calldata right) external pure;
1406 | |
1407 | | /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.
1408 | | function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
1409 | |
1410 | | /// Asserts that two arrays of `bytes` values are not equal.
1411 | | function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure;
1412 | |
1413 | | /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.
1414 | | function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
1415 | |
1416 | | /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.
1417 | | function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;
1418 | |
1419 | | /// Asserts that two `int256` values are not equal.
1420 | | function assertNotEq(int256 left, int256 right) external pure;
1421 | |
1422 | | /// Asserts that two `int256` values are not equal and includes error message into revert string on failure.
1423 | | function assertNotEq(int256 left, int256 right, string calldata error) external pure;
1424 | |
1425 | | /// Asserts that two `address` values are not equal.
1426 | | function assertNotEq(address left, address right) external pure;
1427 | |
1428 | | /// Asserts that two `address` values are not equal and includes error message into revert string on failure.
1429 | | function assertNotEq(address left, address right, string calldata error) external pure;
1430 | |
1431 | | /// Asserts that two `bytes32` values are not equal.
1432 | | function assertNotEq(bytes32 left, bytes32 right) external pure;
1433 | |
1434 | | /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.
1435 | | function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;
1436 | |
1437 | | /// Asserts that the given condition is true.
1438 | | function assertTrue(bool condition) external pure;
1439 | |
1440 | | /// Asserts that the given condition is true and includes error message into revert string on failure.
1441 | | function assertTrue(bool condition, string calldata error) external pure;
1442 | |
1443 | | /// If the condition is false, discard this run's fuzz inputs and generate new ones.
1444 | | function assume(bool condition) external pure;
1445 | |
1446 | | /// Discard this run's fuzz inputs and generate new ones if next call reverted.
1447 | | function assumeNoRevert() external pure;
1448 | |
1449 | | /// Writes a breakpoint to jump to in the debugger.
1450 | | function breakpoint(string calldata char) external;
1451 | |
1452 | | /// Writes a conditional breakpoint to jump to in the debugger.
1453 | | function breakpoint(string calldata char, bool value) external;
1454 | |
1455 | | /// Returns the Foundry version.
1456 | | /// Format: <cargo_version>+<git_sha>+<build_timestamp>
1457 | | /// Sample output: 0.2.0+faa94c384+202407110019
1458 | | /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs.
1459 | | /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000)
1460 | | /// to compare timestamps while ignoring minor time differences.
1461 | | function getFoundryVersion() external view returns (string memory version);
1462 | |
1463 | | /// Returns the RPC url for the given alias.
1464 | | function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
1465 | |
1466 | | /// Returns all rpc urls and their aliases as structs.
1467 | | function rpcUrlStructs() external view returns (Rpc[] memory urls);
1468 | |
1469 | | /// Returns all rpc urls and their aliases `[alias, url][]`.
1470 | | function rpcUrls() external view returns (string[2][] memory urls);
1471 | |
1472 | | /// Suspends execution of the main thread for `duration` milliseconds.
1473 | | function sleep(uint256 duration) external;
1474 | |
1475 | | // ======== Toml ========
1476 | |
1477 | | /// Checks if `key` exists in a TOML table.
1478 | | function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);
1479 | |
1480 | | /// Parses a string of TOML data at `key` and coerces it to `address`.
1481 | | function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address);
1482 | |
1483 | | /// Parses a string of TOML data at `key` and coerces it to `address[]`.
1484 | | function parseTomlAddressArray(string calldata toml, string calldata key)
1485 | | external
1486 | | pure
1487 | | returns (address[] memory);
1488 | |
1489 | | /// Parses a string of TOML data at `key` and coerces it to `bool`.
1490 | | function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool);
1491 | |
1492 | | /// Parses a string of TOML data at `key` and coerces it to `bool[]`.
1493 | | function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory);
1494 | |
1495 | | /// Parses a string of TOML data at `key` and coerces it to `bytes`.
1496 | | function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory);
1497 | |
1498 | | /// Parses a string of TOML data at `key` and coerces it to `bytes32`.
1499 | | function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32);
1500 | |
1501 | | /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.
1502 | | function parseTomlBytes32Array(string calldata toml, string calldata key)
1503 | | external
1504 | | pure
1505 | | returns (bytes32[] memory);
1506 | |
1507 | | /// Parses a string of TOML data at `key` and coerces it to `bytes[]`.
1508 | | function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory);
1509 | |
1510 | | /// Parses a string of TOML data at `key` and coerces it to `int256`.
1511 | | function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256);
1512 | |
1513 | | /// Parses a string of TOML data at `key` and coerces it to `int256[]`.
1514 | | function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory);
1515 | |
1516 | | /// Returns an array of all the keys in a TOML table.
1517 | | function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys);
1518 | |
1519 | | /// Parses a string of TOML data at `key` and coerces it to `string`.
1520 | | function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory);
1521 | |
1522 | | /// Parses a string of TOML data at `key` and coerces it to `string[]`.
1523 | | function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory);
1524 | |
1525 | | /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`.
1526 | | function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription)
1527 | | external
1528 | | pure
1529 | | returns (bytes memory);
1530 | |
1531 | | /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`.
1532 | | function parseTomlType(string calldata toml, string calldata typeDescription)
1533 | | external
1534 | | pure
1535 | | returns (bytes memory);
1536 | |
1537 | | /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`.
1538 | | function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription)
1539 | | external
1540 | | pure
1541 | | returns (bytes memory);
1542 | |
1543 | | /// Parses a string of TOML data at `key` and coerces it to `uint256`.
1544 | | function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256);
1545 | |
1546 | | /// Parses a string of TOML data at `key` and coerces it to `uint256[]`.
1547 | | function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory);
1548 | |
1549 | | /// ABI-encodes a TOML table.
1550 | | function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData);
1551 | |
1552 | | /// ABI-encodes a TOML table at `key`.
1553 | | function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData);
1554 | |
1555 | | /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.
1556 | | function writeToml(string calldata json, string calldata path) external;
1557 | |
1558 | | /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.>
1559 | | /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.
1560 | | function writeToml(string calldata json, string calldata path, string calldata valueKey) external;
1561 | |
1562 | | // ======== Utilities ========
1563 | |
1564 | | /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
1565 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
1566 | | external
1567 | | pure
1568 | | returns (address);
1569 | |
1570 | | /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer.
1571 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);
1572 | |
1573 | | /// Compute the address a contract will be deployed at for a given deployer address and nonce.
1574 | | function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);
1575 | |
1576 | | /// Utility cheatcode to copy storage of `from` contract to another `to` contract.
1577 | | function copyStorage(address from, address to) external;
1578 | |
1579 | | /// Returns ENS namehash for provided string.
1580 | | function ensNamehash(string calldata name) external pure returns (bytes32);
1581 | |
1582 | | /// Gets the label for the specified address.
1583 | | function getLabel(address account) external view returns (string memory currentLabel);
1584 | |
1585 | | /// Labels an address in call traces.
1586 | | function label(address account, string calldata newLabel) external;
1587 | |
1588 | | /// Pauses collection of call traces. Useful in cases when you want to skip tracing of
1589 | | /// complex calls which are not useful for debugging.
1590 | | function pauseTracing() external view;
1591 | |
1592 | | /// Returns a random `address`.
1593 | | function randomAddress() external returns (address);
1594 | |
1595 | | /// Returns an random `bool`.
1596 | | function randomBool() external view returns (bool);
1597 | |
1598 | | /// Returns an random byte array value of the given length.
1599 | | function randomBytes(uint256 len) external view returns (bytes memory);
1600 | |
1601 | | /// Returns an random `int256` value.
1602 | | function randomInt() external view returns (int256);
1603 | |
1604 | | /// Returns an random `int256` value of given bits.
1605 | | function randomInt(uint256 bits) external view returns (int256);
1606 | |
1607 | | /// Returns a random uint256 value.
1608 | | function randomUint() external returns (uint256);
1609 | |
1610 | | /// Returns random uint256 value between the provided range (=min..=max).
1611 | | function randomUint(uint256 min, uint256 max) external returns (uint256);
1612 | |
1613 | | /// Returns an random `uint256` value of given bits.
1614 | | function randomUint(uint256 bits) external view returns (uint256);
1615 | |
1616 | | /// Unpauses collection of call traces.
1617 | | function resumeTracing() external view;
1618 | |
1619 | | /// Utility cheatcode to set arbitrary storage for given target address.
1620 | | function setArbitraryStorage(address target) external;
1621 | |
1622 | | /// Encodes a `bytes` value to a base64url string.
1623 | | function toBase64URL(bytes calldata data) external pure returns (string memory);
1624 | |
1625 | | /// Encodes a `string` value to a base64url string.
1626 | | function toBase64URL(string calldata data) external pure returns (string memory);
1627 | |
1628 | | /// Encodes a `bytes` value to a base64 string.
1629 | | function toBase64(bytes calldata data) external pure returns (string memory);
1630 | |
1631 | | /// Encodes a `string` value to a base64 string.
1632 | | function toBase64(string calldata data) external pure returns (string memory);
1633 | | }
1634 | |
1635 | | /// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
1636 | | /// in tests, but it is not recommended to use these cheats in scripts.
1637 | | interface Vm is VmSafe {
1638 | | // ======== EVM ========
1639 | |
1640 | | /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
1641 | | function activeFork() external view returns (uint256 forkId);
1642 | |
1643 | | /// In forking mode, explicitly grant the given address cheatcode access.
1644 | | function allowCheatcodes(address account) external;
1645 | |
1646 | | /// Sets `block.blobbasefee`
1647 | | function blobBaseFee(uint256 newBlobBaseFee) external;
1648 | |
1649 | | /// Sets the blobhashes in the transaction.
1650 | | /// Not available on EVM versions before Cancun.
1651 | | /// If used on unsupported EVM versions it will revert.
1652 | | function blobhashes(bytes32[] calldata hashes) external;
1653 | |
1654 | | /// Sets `block.chainid`.
1655 | | function chainId(uint256 newChainId) external;
1656 | |
1657 | | /// Clears all mocked calls.
1658 | | function clearMockedCalls() external;
1659 | |
1660 | | /// Sets `block.coinbase`.
1661 | | function coinbase(address newCoinbase) external;
1662 | |
1663 | | /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork.
1664 | | function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
1665 | |
1666 | | /// Creates a new fork with the given endpoint and block and returns the identifier of the fork.
1667 | | function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
1668 | |
1669 | | /// Creates a new fork with the given endpoint and at the block the given transaction was mined in,
1670 | | /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork.
1671 | | function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
1672 | |
1673 | | /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork.
1674 | | function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
1675 | |
1676 | | /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork.
1677 | | function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
1678 | |
1679 | | /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in,
1680 | | /// replays all transaction mined in the block before the transaction, returns the identifier of the fork.
1681 | | function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
1682 | |
1683 | | /// Sets an address' balance.
1684 | | function deal(address account, uint256 newBalance) external;
1685 | |
1686 | | /// Removes the snapshot with the given ID created by `snapshot`.
1687 | | /// Takes the snapshot ID to delete.
1688 | | /// Returns `true` if the snapshot was successfully deleted.
1689 | | /// Returns `false` if the snapshot does not exist.
1690 | | function deleteSnapshot(uint256 snapshotId) external returns (bool success);
1691 | |
1692 | | /// Removes _all_ snapshots previously created by `snapshot`.
1693 | | function deleteSnapshots() external;
1694 | |
1695 | | /// Sets `block.difficulty`.
1696 | | /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
1697 | | /// Reverts if used on unsupported EVM versions.
1698 | | function difficulty(uint256 newDifficulty) external;
1699 | |
1700 | | /// Dump a genesis JSON file's `allocs` to disk.
1701 | | function dumpState(string calldata pathToStateJson) external;
1702 | |
1703 | | /// Sets an address' code.
1704 | | function etch(address target, bytes calldata newRuntimeBytecode) external;
1705 | |
1706 | | /// Sets `block.basefee`.
1707 | | function fee(uint256 newBasefee) external;
1708 | |
1709 | | /// Gets the blockhashes from the current transaction.
1710 | | /// Not available on EVM versions before Cancun.
1711 | | /// If used on unsupported EVM versions it will revert.
1712 | | function getBlobhashes() external view returns (bytes32[] memory hashes);
1713 | |
1714 | | /// Returns true if the account is marked as persistent.
1715 | | function isPersistent(address account) external view returns (bool persistent);
1716 | |
1717 | | /// Load a genesis JSON file's `allocs` into the in-memory revm state.
1718 | | function loadAllocs(string calldata pathToAllocsJson) external;
1719 | |
1720 | | /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
1721 | | /// Meaning, changes made to the state of this account will be kept when switching forks.
1722 | | function makePersistent(address account) external;
1723 | |
1724 | | /// See `makePersistent(address)`.
1725 | | function makePersistent(address account0, address account1) external;
1726 | |
1727 | | /// See `makePersistent(address)`.
1728 | | function makePersistent(address account0, address account1, address account2) external;
1729 | |
1730 | | /// See `makePersistent(address)`.
1731 | | function makePersistent(address[] calldata accounts) external;
1732 | |
1733 | | /// Reverts a call to an address with specified revert data.
1734 | | function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;
1735 | |
1736 | | /// Reverts a call to an address with a specific `msg.value`, with specified revert data.
1737 | | function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
1738 | | external;
1739 | |
1740 | | /// Mocks a call to an address, returning specified data.
1741 | | /// Calldata can either be strict or a partial match, e.g. if you only
1742 | | /// pass a Solidity selector to the expected calldata, then the entire Solidity
1743 | | /// function will be mocked.
1744 | | function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;
1745 | |
1746 | | /// Mocks a call to an address with a specific `msg.value`, returning specified data.
1747 | | /// Calldata match takes precedence over `msg.value` in case of ambiguity.
1748 | | function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;
1749 | |
1750 | | /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls
1751 | | /// `target` with the same calldata. This functionality is similar to a delegate call made to
1752 | | /// `target` contract from `callee`.
1753 | | /// Can be used to substitute a call to a function with another implementation that captures
1754 | | /// the primary logic of the original function but is easier to reason about.
1755 | | /// If calldata is not a strict match then partial match by selector is attempted.
1756 | | function mockFunction(address callee, address target, bytes calldata data) external;
1757 | |
1758 | | /// Sets the *next* call's `msg.sender` to be the input address.
1759 | | function prank(address msgSender) external;
1760 | |
1761 | | /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.
1762 | | function prank(address msgSender, address txOrigin) external;
1763 | |
1764 | | /// Sets `block.prevrandao`.
1765 | | /// Not available on EVM versions before Paris. Use `difficulty` instead.
1766 | | /// If used on unsupported EVM versions it will revert.
1767 | | function prevrandao(bytes32 newPrevrandao) external;
1768 | |
1769 | | /// Sets `block.prevrandao`.
1770 | | /// Not available on EVM versions before Paris. Use `difficulty` instead.
1771 | | /// If used on unsupported EVM versions it will revert.
1772 | | function prevrandao(uint256 newPrevrandao) external;
1773 | |
1774 | | /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification.
1775 | | function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);
1776 | |
1777 | | /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts.
1778 | | function resetNonce(address account) external;
1779 | |
1780 | | /// Revert the state of the EVM to a previous snapshot
1781 | | /// Takes the snapshot ID to revert to.
1782 | | /// Returns `true` if the snapshot was successfully reverted.
1783 | | /// Returns `false` if the snapshot does not exist.
1784 | | /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.
1785 | | function revertTo(uint256 snapshotId) external returns (bool success);
1786 | |
1787 | | /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots
1788 | | /// Takes the snapshot ID to revert to.
1789 | | /// Returns `true` if the snapshot was successfully reverted and deleted.
1790 | | /// Returns `false` if the snapshot does not exist.
1791 | | function revertToAndDelete(uint256 snapshotId) external returns (bool success);
1792 | |
1793 | | /// Revokes persistent status from the address, previously added via `makePersistent`.
1794 | | function revokePersistent(address account) external;
1795 | |
1796 | | /// See `revokePersistent(address)`.
1797 | | function revokePersistent(address[] calldata accounts) external;
1798 | |
1799 | | /// Sets `block.height`.
1800 | | function roll(uint256 newHeight) external;
1801 | |
1802 | | /// Updates the currently active fork to given block number
1803 | | /// This is similar to `roll` but for the currently active fork.
1804 | | function rollFork(uint256 blockNumber) external;
1805 | |
1806 | | /// Updates the currently active fork to given transaction. This will `rollFork` with the number
1807 | | /// of the block the transaction was mined in and replays all transaction mined before it in the block.
1808 | | function rollFork(bytes32 txHash) external;
1809 | |
1810 | | /// Updates the given fork to given block number.
1811 | | function rollFork(uint256 forkId, uint256 blockNumber) external;
1812 | |
1813 | | /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block.
1814 | | function rollFork(uint256 forkId, bytes32 txHash) external;
1815 | |
1816 | | /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
1817 | | function selectFork(uint256 forkId) external;
1818 | |
1819 | | /// Set blockhash for the current block.
1820 | | /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`.
1821 | | function setBlockhash(uint256 blockNumber, bytes32 blockHash) external;
1822 | |
1823 | | /// Sets the nonce of an account. Must be higher than the current nonce of the account.
1824 | | function setNonce(address account, uint64 newNonce) external;
1825 | |
1826 | | /// Sets the nonce of an account to an arbitrary value.
1827 | | function setNonceUnsafe(address account, uint64 newNonce) external;
1828 | |
1829 | | /// Snapshot the current state of the evm.
1830 | | /// Returns the ID of the snapshot that was created.
1831 | | /// To revert a snapshot use `revertTo`.
1832 | | function snapshot() external returns (uint256 snapshotId);
1833 | |
1834 | | /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.
1835 | | function startPrank(address msgSender) external;
1836 | |
1837 | | /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.
1838 | | function startPrank(address msgSender, address txOrigin) external;
1839 | |
1840 | | /// Resets subsequent calls' `msg.sender` to be `address(this)`.
1841 | | function stopPrank() external;
1842 | |
1843 | | /// Stores a value to an address' storage slot.
1844 | | function store(address target, bytes32 slot, bytes32 value) external;
1845 | |
1846 | | /// Fetches the given transaction from the active fork and executes it on the current state.
1847 | | function transact(bytes32 txHash) external;
1848 | |
1849 | | /// Fetches the given transaction from the given fork and executes it on the current state.
1850 | | function transact(uint256 forkId, bytes32 txHash) external;
1851 | |
1852 | | /// Sets `tx.gasprice`.
1853 | | function txGasPrice(uint256 newGasPrice) external;
1854 | |
1855 | | /// Sets `block.timestamp`.
1856 | | function warp(uint256 newTimestamp) external;
1857 | |
1858 | | // ======== Testing ========
1859 | |
1860 | | /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
1861 | | function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;
1862 | |
1863 | | /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
1864 | | function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
1865 | | external;
1866 | |
1867 | | /// Expects a call to an address with the specified calldata.
1868 | | /// Calldata can either be a strict or a partial match.
1869 | | function expectCall(address callee, bytes calldata data) external;
1870 | |
1871 | | /// Expects given number of calls to an address with the specified calldata.
1872 | | function expectCall(address callee, bytes calldata data, uint64 count) external;
1873 | |
1874 | | /// Expects a call to an address with the specified `msg.value` and calldata.
1875 | | function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
1876 | |
1877 | | /// Expects given number of calls to an address with the specified `msg.value` and calldata.
1878 | | function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;
1879 | |
1880 | | /// Expect a call to an address with the specified `msg.value`, gas, and calldata.
1881 | | function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;
1882 | |
1883 | | /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata.
1884 | | function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;
1885 | |
1886 | | /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
1887 | | /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
1888 | | /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
1889 | | function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData)
1890 | | external;
1891 | |
1892 | | /// Same as the previous method, but also checks supplied address against emitting contract.
1893 | | function expectEmitAnonymous(
1894 | | bool checkTopic0,
1895 | | bool checkTopic1,
1896 | | bool checkTopic2,
1897 | | bool checkTopic3,
1898 | | bool checkData,
1899 | | address emitter
1900 | | ) external;
1901 | |
1902 | | /// Prepare an expected anonymous log with all topic and data checks enabled.
1903 | | /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
1904 | | /// logs were emitted in the expected order with the expected topics and data.
1905 | | function expectEmitAnonymous() external;
1906 | |
1907 | | /// Same as the previous method, but also checks supplied address against emitting contract.
1908 | | function expectEmitAnonymous(address emitter) external;
1909 | |
1910 | | /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
1911 | | /// Call this function, then emit an event, then call a function. Internally after the call, we check if
1912 | | /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
1913 | | function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
1914 | |
1915 | | /// Same as the previous method, but also checks supplied address against emitting contract.
1916 | | function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
1917 | | external;
1918 | |
1919 | | /// Prepare an expected log with all topic and data checks enabled.
1920 | | /// Call this function, then emit an event, then call a function. Internally after the call, we check if
1921 | | /// logs were emitted in the expected order with the expected topics and data.
1922 | | function expectEmit() external;
1923 | |
1924 | | /// Same as the previous method, but also checks supplied address against emitting contract.
1925 | | function expectEmit(address emitter) external;
1926 | |
1927 | | /// Expects an error on next call that starts with the revert data.
1928 | | function expectPartialRevert(bytes4 revertData) external;
1929 | |
1930 | | /// Expects an error on next call to reverter address, that starts with the revert data.
1931 | | function expectPartialRevert(bytes4 revertData, address reverter) external;
1932 | |
1933 | | /// Expects an error on next call with any revert data.
1934 | | function expectRevert() external;
1935 | |
1936 | | /// Expects an error on next call that exactly matches the revert data.
1937 | | function expectRevert(bytes4 revertData) external;
1938 | |
1939 | | /// Expects an error on next call that exactly matches the revert data.
1940 | | function expectRevert(bytes calldata revertData) external;
1941 | |
1942 | | /// Expects an error with any revert data on next call to reverter address.
1943 | | function expectRevert(address reverter) external;
1944 | |
1945 | | /// Expects an error from reverter address on next call, with any revert data.
1946 | | function expectRevert(bytes4 revertData, address reverter) external;
1947 | |
1948 | | /// Expects an error from reverter address on next call, that exactly matches the revert data.
1949 | | function expectRevert(bytes calldata revertData, address reverter) external;
1950 | |
1951 | | /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
1952 | | /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
1953 | | function expectSafeMemory(uint64 min, uint64 max) external;
1954 | |
1955 | | /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
1956 | | /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
1957 | | /// to the set.
1958 | | function expectSafeMemoryCall(uint64 min, uint64 max) external;
1959 | |
1960 | | /// Marks a test as skipped. Must be called at the top level of a test.
1961 | | function skip(bool skipTest) external;
1962 | |
1963 | | /// Marks a test as skipped with a reason. Must be called at the top level of a test.
1964 | | function skip(bool skipTest, string calldata reason) external;
1965 | |
1966 | | /// Stops all safe memory expectation in the current subcontext.
1967 | | function stopExpectSafeMemory() external;
1968 | | }
1969 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/console.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.4.22 <0.9.0;
3 | |
4 | * | library console {
5 | | address constant CONSOLE_ADDRESS =
6 | | 0x000000000000000000636F6e736F6c652e6c6f67;
7 | |
8 | | function _sendLogPayloadImplementation(bytes memory payload) internal view {
9 | | address consoleAddress = CONSOLE_ADDRESS;
10 | | /// @solidity memory-safe-assembly
11 | | assembly {
12 | | pop(
13 | | staticcall(
14 | | gas(),
15 | | consoleAddress,
16 | | add(payload, 32),
17 | | mload(payload),
18 | | 0,
19 | | 0
20 | | )
21 | | )
22 | | }
23 | | }
24 | |
25 | | function _castToPure(
26 | | function(bytes memory) internal view fnIn
27 | | ) internal pure returns (function(bytes memory) pure fnOut) {
28 | | assembly {
29 | | fnOut := fnIn
30 | | }
31 | | }
32 | |
33 | | function _sendLogPayload(bytes memory payload) internal pure {
34 | | _castToPure(_sendLogPayloadImplementation)(payload);
35 | | }
36 | |
37 | | function log() internal pure {
38 | | _sendLogPayload(abi.encodeWithSignature("log()"));
39 | | }
40 | |
41 | | function logInt(int256 p0) internal pure {
42 | | _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
43 | | }
44 | |
45 | | function logUint(uint256 p0) internal pure {
46 | | _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
47 | | }
48 | |
49 | | function logString(string memory p0) internal pure {
50 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
51 | | }
52 | |
53 | | function logBool(bool p0) internal pure {
54 | | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
55 | | }
56 | |
57 | | function logAddress(address p0) internal pure {
58 | | _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
59 | | }
60 | |
61 | | function logBytes(bytes memory p0) internal pure {
62 | | _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
63 | | }
64 | |
65 | | function logBytes1(bytes1 p0) internal pure {
66 | | _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
67 | | }
68 | |
69 | | function logBytes2(bytes2 p0) internal pure {
70 | | _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
71 | | }
72 | |
73 | | function logBytes3(bytes3 p0) internal pure {
74 | | _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
75 | | }
76 | |
77 | | function logBytes4(bytes4 p0) internal pure {
78 | | _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
79 | | }
80 | |
81 | | function logBytes5(bytes5 p0) internal pure {
82 | | _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
83 | | }
84 | |
85 | | function logBytes6(bytes6 p0) internal pure {
86 | | _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
87 | | }
88 | |
89 | | function logBytes7(bytes7 p0) internal pure {
90 | | _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
91 | | }
92 | |
93 | | function logBytes8(bytes8 p0) internal pure {
94 | | _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
95 | | }
96 | |
97 | | function logBytes9(bytes9 p0) internal pure {
98 | | _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
99 | | }
100 | |
101 | | function logBytes10(bytes10 p0) internal pure {
102 | | _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
103 | | }
104 | |
105 | | function logBytes11(bytes11 p0) internal pure {
106 | | _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
107 | | }
108 | |
109 | | function logBytes12(bytes12 p0) internal pure {
110 | | _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
111 | | }
112 | |
113 | | function logBytes13(bytes13 p0) internal pure {
114 | | _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
115 | | }
116 | |
117 | | function logBytes14(bytes14 p0) internal pure {
118 | | _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
119 | | }
120 | |
121 | | function logBytes15(bytes15 p0) internal pure {
122 | | _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
123 | | }
124 | |
125 | | function logBytes16(bytes16 p0) internal pure {
126 | | _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
127 | | }
128 | |
129 | | function logBytes17(bytes17 p0) internal pure {
130 | | _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
131 | | }
132 | |
133 | | function logBytes18(bytes18 p0) internal pure {
134 | | _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
135 | | }
136 | |
137 | | function logBytes19(bytes19 p0) internal pure {
138 | | _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
139 | | }
140 | |
141 | | function logBytes20(bytes20 p0) internal pure {
142 | | _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
143 | | }
144 | |
145 | | function logBytes21(bytes21 p0) internal pure {
146 | | _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
147 | | }
148 | |
149 | | function logBytes22(bytes22 p0) internal pure {
150 | | _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
151 | | }
152 | |
153 | | function logBytes23(bytes23 p0) internal pure {
154 | | _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
155 | | }
156 | |
157 | | function logBytes24(bytes24 p0) internal pure {
158 | | _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
159 | | }
160 | |
161 | | function logBytes25(bytes25 p0) internal pure {
162 | | _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
163 | | }
164 | |
165 | | function logBytes26(bytes26 p0) internal pure {
166 | | _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
167 | | }
168 | |
169 | | function logBytes27(bytes27 p0) internal pure {
170 | | _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
171 | | }
172 | |
173 | | function logBytes28(bytes28 p0) internal pure {
174 | | _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
175 | | }
176 | |
177 | | function logBytes29(bytes29 p0) internal pure {
178 | | _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
179 | | }
180 | |
181 | | function logBytes30(bytes30 p0) internal pure {
182 | | _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
183 | | }
184 | |
185 | | function logBytes31(bytes31 p0) internal pure {
186 | | _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
187 | | }
188 | |
189 | | function logBytes32(bytes32 p0) internal pure {
190 | | _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
191 | | }
192 | |
193 | | function log(uint256 p0) internal pure {
194 | | _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
195 | | }
196 | |
197 | | function log(int256 p0) internal pure {
198 | | _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
199 | | }
200 | |
201 | | function log(string memory p0) internal pure {
202 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
203 | | }
204 | |
205 | | function log(bool p0) internal pure {
206 | | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
207 | | }
208 | |
209 | | function log(address p0) internal pure {
210 | | _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
211 | | }
212 | |
213 | | function log(uint256 p0, uint256 p1) internal pure {
214 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
215 | | }
216 | |
217 | | function log(uint256 p0, string memory p1) internal pure {
218 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
219 | | }
220 | |
221 | | function log(uint256 p0, bool p1) internal pure {
222 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
223 | | }
224 | |
225 | | function log(uint256 p0, address p1) internal pure {
226 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
227 | | }
228 | |
229 | | function log(string memory p0, uint256 p1) internal pure {
230 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
231 | | }
232 | |
233 | | function log(string memory p0, int256 p1) internal pure {
234 | | _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
235 | | }
236 | |
237 | | function log(string memory p0, string memory p1) internal pure {
238 | | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
239 | | }
240 | |
241 | | function log(string memory p0, bool p1) internal pure {
242 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
243 | | }
244 | |
245 | | function log(string memory p0, address p1) internal pure {
246 | | _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
247 | | }
248 | |
249 | | function log(bool p0, uint256 p1) internal pure {
250 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
251 | | }
252 | |
253 | | function log(bool p0, string memory p1) internal pure {
254 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
255 | | }
256 | |
257 | | function log(bool p0, bool p1) internal pure {
258 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
259 | | }
260 | |
261 | | function log(bool p0, address p1) internal pure {
262 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
263 | | }
264 | |
265 | | function log(address p0, uint256 p1) internal pure {
266 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
267 | | }
268 | |
269 | | function log(address p0, string memory p1) internal pure {
270 | | _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
271 | | }
272 | |
273 | | function log(address p0, bool p1) internal pure {
274 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
275 | | }
276 | |
277 | | function log(address p0, address p1) internal pure {
278 | | _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
279 | | }
280 | |
281 | | function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
282 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
283 | | }
284 | |
285 | | function log(uint256 p0, uint256 p1, string memory p2) internal pure {
286 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
287 | | }
288 | |
289 | | function log(uint256 p0, uint256 p1, bool p2) internal pure {
290 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
291 | | }
292 | |
293 | | function log(uint256 p0, uint256 p1, address p2) internal pure {
294 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
295 | | }
296 | |
297 | | function log(uint256 p0, string memory p1, uint256 p2) internal pure {
298 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
299 | | }
300 | |
301 | | function log(uint256 p0, string memory p1, string memory p2) internal pure {
302 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
303 | | }
304 | |
305 | | function log(uint256 p0, string memory p1, bool p2) internal pure {
306 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
307 | | }
308 | |
309 | | function log(uint256 p0, string memory p1, address p2) internal pure {
310 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
311 | | }
312 | |
313 | | function log(uint256 p0, bool p1, uint256 p2) internal pure {
314 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
315 | | }
316 | |
317 | | function log(uint256 p0, bool p1, string memory p2) internal pure {
318 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
319 | | }
320 | |
321 | | function log(uint256 p0, bool p1, bool p2) internal pure {
322 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
323 | | }
324 | |
325 | | function log(uint256 p0, bool p1, address p2) internal pure {
326 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
327 | | }
328 | |
329 | | function log(uint256 p0, address p1, uint256 p2) internal pure {
330 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
331 | | }
332 | |
333 | | function log(uint256 p0, address p1, string memory p2) internal pure {
334 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
335 | | }
336 | |
337 | | function log(uint256 p0, address p1, bool p2) internal pure {
338 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
339 | | }
340 | |
341 | | function log(uint256 p0, address p1, address p2) internal pure {
342 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
343 | | }
344 | |
345 | | function log(string memory p0, uint256 p1, uint256 p2) internal pure {
346 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
347 | | }
348 | |
349 | | function log(string memory p0, uint256 p1, string memory p2) internal pure {
350 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
351 | | }
352 | |
353 | | function log(string memory p0, uint256 p1, bool p2) internal pure {
354 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
355 | | }
356 | |
357 | | function log(string memory p0, uint256 p1, address p2) internal pure {
358 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
359 | | }
360 | |
361 | | function log(string memory p0, string memory p1, uint256 p2) internal pure {
362 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
363 | | }
364 | |
365 | | function log(string memory p0, string memory p1, string memory p2) internal pure {
366 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
367 | | }
368 | |
369 | | function log(string memory p0, string memory p1, bool p2) internal pure {
370 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
371 | | }
372 | |
373 | | function log(string memory p0, string memory p1, address p2) internal pure {
374 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
375 | | }
376 | |
377 | | function log(string memory p0, bool p1, uint256 p2) internal pure {
378 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
379 | | }
380 | |
381 | | function log(string memory p0, bool p1, string memory p2) internal pure {
382 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
383 | | }
384 | |
385 | | function log(string memory p0, bool p1, bool p2) internal pure {
386 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
387 | | }
388 | |
389 | | function log(string memory p0, bool p1, address p2) internal pure {
390 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
391 | | }
392 | |
393 | | function log(string memory p0, address p1, uint256 p2) internal pure {
394 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
395 | | }
396 | |
397 | | function log(string memory p0, address p1, string memory p2) internal pure {
398 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
399 | | }
400 | |
401 | | function log(string memory p0, address p1, bool p2) internal pure {
402 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
403 | | }
404 | |
405 | | function log(string memory p0, address p1, address p2) internal pure {
406 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
407 | | }
408 | |
409 | | function log(bool p0, uint256 p1, uint256 p2) internal pure {
410 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
411 | | }
412 | |
413 | | function log(bool p0, uint256 p1, string memory p2) internal pure {
414 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
415 | | }
416 | |
417 | | function log(bool p0, uint256 p1, bool p2) internal pure {
418 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
419 | | }
420 | |
421 | | function log(bool p0, uint256 p1, address p2) internal pure {
422 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
423 | | }
424 | |
425 | | function log(bool p0, string memory p1, uint256 p2) internal pure {
426 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
427 | | }
428 | |
429 | | function log(bool p0, string memory p1, string memory p2) internal pure {
430 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
431 | | }
432 | |
433 | | function log(bool p0, string memory p1, bool p2) internal pure {
434 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
435 | | }
436 | |
437 | | function log(bool p0, string memory p1, address p2) internal pure {
438 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
439 | | }
440 | |
441 | | function log(bool p0, bool p1, uint256 p2) internal pure {
442 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
443 | | }
444 | |
445 | | function log(bool p0, bool p1, string memory p2) internal pure {
446 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
447 | | }
448 | |
449 | | function log(bool p0, bool p1, bool p2) internal pure {
450 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
451 | | }
452 | |
453 | | function log(bool p0, bool p1, address p2) internal pure {
454 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
455 | | }
456 | |
457 | | function log(bool p0, address p1, uint256 p2) internal pure {
458 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
459 | | }
460 | |
461 | | function log(bool p0, address p1, string memory p2) internal pure {
462 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
463 | | }
464 | |
465 | | function log(bool p0, address p1, bool p2) internal pure {
466 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
467 | | }
468 | |
469 | | function log(bool p0, address p1, address p2) internal pure {
470 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
471 | | }
472 | |
473 | | function log(address p0, uint256 p1, uint256 p2) internal pure {
474 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
475 | | }
476 | |
477 | | function log(address p0, uint256 p1, string memory p2) internal pure {
478 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
479 | | }
480 | |
481 | | function log(address p0, uint256 p1, bool p2) internal pure {
482 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
483 | | }
484 | |
485 | | function log(address p0, uint256 p1, address p2) internal pure {
486 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
487 | | }
488 | |
489 | | function log(address p0, string memory p1, uint256 p2) internal pure {
490 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
491 | | }
492 | |
493 | | function log(address p0, string memory p1, string memory p2) internal pure {
494 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
495 | | }
496 | |
497 | | function log(address p0, string memory p1, bool p2) internal pure {
498 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
499 | | }
500 | |
501 | | function log(address p0, string memory p1, address p2) internal pure {
502 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
503 | | }
504 | |
505 | | function log(address p0, bool p1, uint256 p2) internal pure {
506 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
507 | | }
508 | |
509 | | function log(address p0, bool p1, string memory p2) internal pure {
510 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
511 | | }
512 | |
513 | | function log(address p0, bool p1, bool p2) internal pure {
514 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
515 | | }
516 | |
517 | | function log(address p0, bool p1, address p2) internal pure {
518 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
519 | | }
520 | |
521 | | function log(address p0, address p1, uint256 p2) internal pure {
522 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
523 | | }
524 | |
525 | | function log(address p0, address p1, string memory p2) internal pure {
526 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
527 | | }
528 | |
529 | | function log(address p0, address p1, bool p2) internal pure {
530 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
531 | | }
532 | |
533 | | function log(address p0, address p1, address p2) internal pure {
534 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
535 | | }
536 | |
537 | | function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
538 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
539 | | }
540 | |
541 | | function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
542 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
543 | | }
544 | |
545 | | function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
546 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
547 | | }
548 | |
549 | | function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
550 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
551 | | }
552 | |
553 | | function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
554 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
555 | | }
556 | |
557 | | function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
558 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
559 | | }
560 | |
561 | | function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
562 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
563 | | }
564 | |
565 | | function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
566 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
567 | | }
568 | |
569 | | function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
570 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
571 | | }
572 | |
573 | | function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
574 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
575 | | }
576 | |
577 | | function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
578 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
579 | | }
580 | |
581 | | function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
582 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
583 | | }
584 | |
585 | | function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
586 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
587 | | }
588 | |
589 | | function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
590 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
591 | | }
592 | |
593 | | function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
594 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
595 | | }
596 | |
597 | | function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
598 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
599 | | }
600 | |
601 | | function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
602 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
603 | | }
604 | |
605 | | function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
606 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
607 | | }
608 | |
609 | | function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
610 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
611 | | }
612 | |
613 | | function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
614 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
615 | | }
616 | |
617 | | function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
618 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
619 | | }
620 | |
621 | | function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
622 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
623 | | }
624 | |
625 | | function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
626 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
627 | | }
628 | |
629 | | function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
630 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
631 | | }
632 | |
633 | | function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
634 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
635 | | }
636 | |
637 | | function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
638 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
639 | | }
640 | |
641 | | function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
642 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
643 | | }
644 | |
645 | | function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
646 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
647 | | }
648 | |
649 | | function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
650 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
651 | | }
652 | |
653 | | function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
654 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
655 | | }
656 | |
657 | | function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
658 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
659 | | }
660 | |
661 | | function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
662 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
663 | | }
664 | |
665 | | function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
666 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
667 | | }
668 | |
669 | | function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
670 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
671 | | }
672 | |
673 | | function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
674 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
675 | | }
676 | |
677 | | function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
678 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
679 | | }
680 | |
681 | | function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
682 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
683 | | }
684 | |
685 | | function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
686 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
687 | | }
688 | |
689 | | function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
690 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
691 | | }
692 | |
693 | | function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
694 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
695 | | }
696 | |
697 | | function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
698 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
699 | | }
700 | |
701 | | function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
702 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
703 | | }
704 | |
705 | | function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
706 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
707 | | }
708 | |
709 | | function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
710 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
711 | | }
712 | |
713 | | function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
714 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
715 | | }
716 | |
717 | | function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
718 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
719 | | }
720 | |
721 | | function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
722 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
723 | | }
724 | |
725 | | function log(uint256 p0, bool p1, address p2, address p3) internal pure {
726 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
727 | | }
728 | |
729 | | function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
730 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
731 | | }
732 | |
733 | | function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
734 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
735 | | }
736 | |
737 | | function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
738 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
739 | | }
740 | |
741 | | function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
742 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
743 | | }
744 | |
745 | | function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
746 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
747 | | }
748 | |
749 | | function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
750 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
751 | | }
752 | |
753 | | function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
754 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
755 | | }
756 | |
757 | | function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
758 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
759 | | }
760 | |
761 | | function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
762 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
763 | | }
764 | |
765 | | function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
766 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
767 | | }
768 | |
769 | | function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
770 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
771 | | }
772 | |
773 | | function log(uint256 p0, address p1, bool p2, address p3) internal pure {
774 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
775 | | }
776 | |
777 | | function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
778 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
779 | | }
780 | |
781 | | function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
782 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
783 | | }
784 | |
785 | | function log(uint256 p0, address p1, address p2, bool p3) internal pure {
786 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
787 | | }
788 | |
789 | | function log(uint256 p0, address p1, address p2, address p3) internal pure {
790 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
791 | | }
792 | |
793 | | function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
794 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
795 | | }
796 | |
797 | | function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
798 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
799 | | }
800 | |
801 | | function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
802 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
803 | | }
804 | |
805 | | function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
806 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
807 | | }
808 | |
809 | | function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
810 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
811 | | }
812 | |
813 | | function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
814 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
815 | | }
816 | |
817 | | function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
818 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
819 | | }
820 | |
821 | | function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
822 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
823 | | }
824 | |
825 | | function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
826 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
827 | | }
828 | |
829 | | function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
830 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
831 | | }
832 | |
833 | | function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
834 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
835 | | }
836 | |
837 | | function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
838 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
839 | | }
840 | |
841 | | function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
842 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
843 | | }
844 | |
845 | | function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
846 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
847 | | }
848 | |
849 | | function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
850 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
851 | | }
852 | |
853 | | function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
854 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
855 | | }
856 | |
857 | | function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
858 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
859 | | }
860 | |
861 | | function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
862 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
863 | | }
864 | |
865 | | function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
866 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
867 | | }
868 | |
869 | | function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
870 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
871 | | }
872 | |
873 | | function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
874 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
875 | | }
876 | |
877 | | function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
878 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
879 | | }
880 | |
881 | | function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
882 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
883 | | }
884 | |
885 | | function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
886 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
887 | | }
888 | |
889 | | function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
890 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
891 | | }
892 | |
893 | | function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
894 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
895 | | }
896 | |
897 | | function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
898 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
899 | | }
900 | |
901 | | function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
902 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
903 | | }
904 | |
905 | | function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
906 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
907 | | }
908 | |
909 | | function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
910 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
911 | | }
912 | |
913 | | function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
914 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
915 | | }
916 | |
917 | | function log(string memory p0, string memory p1, address p2, address p3) internal pure {
918 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
919 | | }
920 | |
921 | | function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
922 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
923 | | }
924 | |
925 | | function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
926 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
927 | | }
928 | |
929 | | function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
930 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
931 | | }
932 | |
933 | | function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
934 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
935 | | }
936 | |
937 | | function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
938 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
939 | | }
940 | |
941 | | function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
942 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
943 | | }
944 | |
945 | | function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
946 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
947 | | }
948 | |
949 | | function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
950 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
951 | | }
952 | |
953 | | function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
954 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
955 | | }
956 | |
957 | | function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
958 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
959 | | }
960 | |
961 | | function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
962 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
963 | | }
964 | |
965 | | function log(string memory p0, bool p1, bool p2, address p3) internal pure {
966 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
967 | | }
968 | |
969 | | function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
970 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
971 | | }
972 | |
973 | | function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
974 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
975 | | }
976 | |
977 | | function log(string memory p0, bool p1, address p2, bool p3) internal pure {
978 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
979 | | }
980 | |
981 | | function log(string memory p0, bool p1, address p2, address p3) internal pure {
982 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
983 | | }
984 | |
985 | | function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
986 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
987 | | }
988 | |
989 | | function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
990 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
991 | | }
992 | |
993 | | function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
994 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
995 | | }
996 | |
997 | | function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
998 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
999 | | }
1000 | |
1001 | | function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
1002 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
1003 | | }
1004 | |
1005 | | function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
1006 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
1007 | | }
1008 | |
1009 | | function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
1010 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
1011 | | }
1012 | |
1013 | | function log(string memory p0, address p1, string memory p2, address p3) internal pure {
1014 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
1015 | | }
1016 | |
1017 | | function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
1018 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
1019 | | }
1020 | |
1021 | | function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
1022 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
1023 | | }
1024 | |
1025 | | function log(string memory p0, address p1, bool p2, bool p3) internal pure {
1026 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
1027 | | }
1028 | |
1029 | | function log(string memory p0, address p1, bool p2, address p3) internal pure {
1030 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
1031 | | }
1032 | |
1033 | | function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
1034 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
1035 | | }
1036 | |
1037 | | function log(string memory p0, address p1, address p2, string memory p3) internal pure {
1038 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
1039 | | }
1040 | |
1041 | | function log(string memory p0, address p1, address p2, bool p3) internal pure {
1042 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
1043 | | }
1044 | |
1045 | | function log(string memory p0, address p1, address p2, address p3) internal pure {
1046 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
1047 | | }
1048 | |
1049 | | function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
1050 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
1051 | | }
1052 | |
1053 | | function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
1054 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
1055 | | }
1056 | |
1057 | | function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
1058 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
1059 | | }
1060 | |
1061 | | function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
1062 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
1063 | | }
1064 | |
1065 | | function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
1066 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
1067 | | }
1068 | |
1069 | | function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
1070 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
1071 | | }
1072 | |
1073 | | function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
1074 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
1075 | | }
1076 | |
1077 | | function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
1078 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
1079 | | }
1080 | |
1081 | | function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
1082 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
1083 | | }
1084 | |
1085 | | function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
1086 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
1087 | | }
1088 | |
1089 | | function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
1090 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
1091 | | }
1092 | |
1093 | | function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
1094 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
1095 | | }
1096 | |
1097 | | function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
1098 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
1099 | | }
1100 | |
1101 | | function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
1102 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
1103 | | }
1104 | |
1105 | | function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
1106 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
1107 | | }
1108 | |
1109 | | function log(bool p0, uint256 p1, address p2, address p3) internal pure {
1110 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
1111 | | }
1112 | |
1113 | | function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
1114 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
1115 | | }
1116 | |
1117 | | function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
1118 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
1119 | | }
1120 | |
1121 | | function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
1122 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
1123 | | }
1124 | |
1125 | | function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
1126 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
1127 | | }
1128 | |
1129 | | function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
1130 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
1131 | | }
1132 | |
1133 | | function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
1134 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
1135 | | }
1136 | |
1137 | | function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
1138 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
1139 | | }
1140 | |
1141 | | function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
1142 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
1143 | | }
1144 | |
1145 | | function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
1146 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
1147 | | }
1148 | |
1149 | | function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
1150 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
1151 | | }
1152 | |
1153 | | function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
1154 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
1155 | | }
1156 | |
1157 | | function log(bool p0, string memory p1, bool p2, address p3) internal pure {
1158 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
1159 | | }
1160 | |
1161 | | function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
1162 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
1163 | | }
1164 | |
1165 | | function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
1166 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
1167 | | }
1168 | |
1169 | | function log(bool p0, string memory p1, address p2, bool p3) internal pure {
1170 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
1171 | | }
1172 | |
1173 | | function log(bool p0, string memory p1, address p2, address p3) internal pure {
1174 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
1175 | | }
1176 | |
1177 | | function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
1178 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
1179 | | }
1180 | |
1181 | | function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
1182 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
1183 | | }
1184 | |
1185 | | function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
1186 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
1187 | | }
1188 | |
1189 | | function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
1190 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
1191 | | }
1192 | |
1193 | | function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
1194 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
1195 | | }
1196 | |
1197 | | function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
1198 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
1199 | | }
1200 | |
1201 | | function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
1202 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
1203 | | }
1204 | |
1205 | | function log(bool p0, bool p1, string memory p2, address p3) internal pure {
1206 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
1207 | | }
1208 | |
1209 | | function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
1210 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
1211 | | }
1212 | |
1213 | | function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
1214 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
1215 | | }
1216 | |
1217 | | function log(bool p0, bool p1, bool p2, bool p3) internal pure {
1218 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
1219 | | }
1220 | |
1221 | | function log(bool p0, bool p1, bool p2, address p3) internal pure {
1222 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
1223 | | }
1224 | |
1225 | | function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
1226 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
1227 | | }
1228 | |
1229 | | function log(bool p0, bool p1, address p2, string memory p3) internal pure {
1230 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
1231 | | }
1232 | |
1233 | | function log(bool p0, bool p1, address p2, bool p3) internal pure {
1234 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
1235 | | }
1236 | |
1237 | | function log(bool p0, bool p1, address p2, address p3) internal pure {
1238 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
1239 | | }
1240 | |
1241 | | function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
1242 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
1243 | | }
1244 | |
1245 | | function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
1246 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
1247 | | }
1248 | |
1249 | | function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
1250 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
1251 | | }
1252 | |
1253 | | function log(bool p0, address p1, uint256 p2, address p3) internal pure {
1254 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
1255 | | }
1256 | |
1257 | | function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
1258 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
1259 | | }
1260 | |
1261 | | function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
1262 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
1263 | | }
1264 | |
1265 | | function log(bool p0, address p1, string memory p2, bool p3) internal pure {
1266 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
1267 | | }
1268 | |
1269 | | function log(bool p0, address p1, string memory p2, address p3) internal pure {
1270 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
1271 | | }
1272 | |
1273 | | function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
1274 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
1275 | | }
1276 | |
1277 | | function log(bool p0, address p1, bool p2, string memory p3) internal pure {
1278 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
1279 | | }
1280 | |
1281 | | function log(bool p0, address p1, bool p2, bool p3) internal pure {
1282 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
1283 | | }
1284 | |
1285 | | function log(bool p0, address p1, bool p2, address p3) internal pure {
1286 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
1287 | | }
1288 | |
1289 | | function log(bool p0, address p1, address p2, uint256 p3) internal pure {
1290 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
1291 | | }
1292 | |
1293 | | function log(bool p0, address p1, address p2, string memory p3) internal pure {
1294 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
1295 | | }
1296 | |
1297 | | function log(bool p0, address p1, address p2, bool p3) internal pure {
1298 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
1299 | | }
1300 | |
1301 | | function log(bool p0, address p1, address p2, address p3) internal pure {
1302 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
1303 | | }
1304 | |
1305 | | function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
1306 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
1307 | | }
1308 | |
1309 | | function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
1310 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
1311 | | }
1312 | |
1313 | | function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
1314 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
1315 | | }
1316 | |
1317 | | function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
1318 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
1319 | | }
1320 | |
1321 | | function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
1322 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
1323 | | }
1324 | |
1325 | | function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
1326 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
1327 | | }
1328 | |
1329 | | function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
1330 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
1331 | | }
1332 | |
1333 | | function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
1334 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
1335 | | }
1336 | |
1337 | | function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
1338 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
1339 | | }
1340 | |
1341 | | function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
1342 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
1343 | | }
1344 | |
1345 | | function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
1346 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
1347 | | }
1348 | |
1349 | | function log(address p0, uint256 p1, bool p2, address p3) internal pure {
1350 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
1351 | | }
1352 | |
1353 | | function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
1354 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
1355 | | }
1356 | |
1357 | | function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
1358 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
1359 | | }
1360 | |
1361 | | function log(address p0, uint256 p1, address p2, bool p3) internal pure {
1362 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
1363 | | }
1364 | |
1365 | | function log(address p0, uint256 p1, address p2, address p3) internal pure {
1366 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
1367 | | }
1368 | |
1369 | | function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
1370 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
1371 | | }
1372 | |
1373 | | function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
1374 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
1375 | | }
1376 | |
1377 | | function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
1378 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
1379 | | }
1380 | |
1381 | | function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
1382 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
1383 | | }
1384 | |
1385 | | function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
1386 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
1387 | | }
1388 | |
1389 | | function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
1390 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
1391 | | }
1392 | |
1393 | | function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
1394 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
1395 | | }
1396 | |
1397 | | function log(address p0, string memory p1, string memory p2, address p3) internal pure {
1398 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
1399 | | }
1400 | |
1401 | | function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
1402 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
1403 | | }
1404 | |
1405 | | function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
1406 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
1407 | | }
1408 | |
1409 | | function log(address p0, string memory p1, bool p2, bool p3) internal pure {
1410 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
1411 | | }
1412 | |
1413 | | function log(address p0, string memory p1, bool p2, address p3) internal pure {
1414 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
1415 | | }
1416 | |
1417 | | function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
1418 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
1419 | | }
1420 | |
1421 | | function log(address p0, string memory p1, address p2, string memory p3) internal pure {
1422 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
1423 | | }
1424 | |
1425 | | function log(address p0, string memory p1, address p2, bool p3) internal pure {
1426 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
1427 | | }
1428 | |
1429 | | function log(address p0, string memory p1, address p2, address p3) internal pure {
1430 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
1431 | | }
1432 | |
1433 | | function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
1434 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
1435 | | }
1436 | |
1437 | | function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
1438 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
1439 | | }
1440 | |
1441 | | function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
1442 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
1443 | | }
1444 | |
1445 | | function log(address p0, bool p1, uint256 p2, address p3) internal pure {
1446 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
1447 | | }
1448 | |
1449 | | function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
1450 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
1451 | | }
1452 | |
1453 | | function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
1454 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
1455 | | }
1456 | |
1457 | | function log(address p0, bool p1, string memory p2, bool p3) internal pure {
1458 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
1459 | | }
1460 | |
1461 | | function log(address p0, bool p1, string memory p2, address p3) internal pure {
1462 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
1463 | | }
1464 | |
1465 | | function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
1466 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
1467 | | }
1468 | |
1469 | | function log(address p0, bool p1, bool p2, string memory p3) internal pure {
1470 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
1471 | | }
1472 | |
1473 | | function log(address p0, bool p1, bool p2, bool p3) internal pure {
1474 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
1475 | | }
1476 | |
1477 | | function log(address p0, bool p1, bool p2, address p3) internal pure {
1478 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
1479 | | }
1480 | |
1481 | | function log(address p0, bool p1, address p2, uint256 p3) internal pure {
1482 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
1483 | | }
1484 | |
1485 | | function log(address p0, bool p1, address p2, string memory p3) internal pure {
1486 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
1487 | | }
1488 | |
1489 | | function log(address p0, bool p1, address p2, bool p3) internal pure {
1490 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
1491 | | }
1492 | |
1493 | | function log(address p0, bool p1, address p2, address p3) internal pure {
1494 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
1495 | | }
1496 | |
1497 | | function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
1498 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
1499 | | }
1500 | |
1501 | | function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
1502 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
1503 | | }
1504 | |
1505 | | function log(address p0, address p1, uint256 p2, bool p3) internal pure {
1506 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
1507 | | }
1508 | |
1509 | | function log(address p0, address p1, uint256 p2, address p3) internal pure {
1510 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
1511 | | }
1512 | |
1513 | | function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
1514 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
1515 | | }
1516 | |
1517 | | function log(address p0, address p1, string memory p2, string memory p3) internal pure {
1518 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
1519 | | }
1520 | |
1521 | | function log(address p0, address p1, string memory p2, bool p3) internal pure {
1522 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
1523 | | }
1524 | |
1525 | | function log(address p0, address p1, string memory p2, address p3) internal pure {
1526 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
1527 | | }
1528 | |
1529 | | function log(address p0, address p1, bool p2, uint256 p3) internal pure {
1530 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
1531 | | }
1532 | |
1533 | | function log(address p0, address p1, bool p2, string memory p3) internal pure {
1534 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
1535 | | }
1536 | |
1537 | | function log(address p0, address p1, bool p2, bool p3) internal pure {
1538 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
1539 | | }
1540 | |
1541 | | function log(address p0, address p1, bool p2, address p3) internal pure {
1542 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
1543 | | }
1544 | |
1545 | | function log(address p0, address p1, address p2, uint256 p3) internal pure {
1546 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
1547 | | }
1548 | |
1549 | | function log(address p0, address p1, address p2, string memory p3) internal pure {
1550 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
1551 | | }
1552 | |
1553 | | function log(address p0, address p1, address p2, bool p3) internal pure {
1554 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
1555 | | }
1556 | |
1557 | | function log(address p0, address p1, address p2, address p3) internal pure {
1558 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
1559 | | }
1560 | | }
1561 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/console2.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.4.22 <0.9.0;
3 | |
4 | | import {console as console2} from "./console.sol";
5 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC165.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2;
3 | |
4 | | interface IERC165 {
5 | | /// @notice Query if a contract implements an interface
6 | | /// @param interfaceID The interface identifier, as specified in ERC-165
7 | | /// @dev Interface identification is specified in ERC-165. This function
8 | | /// uses less than 30,000 gas.
9 | | /// @return `true` if the contract implements `interfaceID` and
10 | | /// `interfaceID` is not 0xffffffff, `false` otherwise
11 | | function supportsInterface(bytes4 interfaceID) external view returns (bool);
12 | | }
13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC20.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2;
3 | |
4 | | /// @dev Interface of the ERC20 standard as defined in the EIP.
5 | | /// @dev This includes the optional name, symbol, and decimals metadata.
6 | | interface IERC20 {
7 | | /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
8 | | event Transfer(address indexed from, address indexed to, uint256 value);
9 | |
10 | | /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
11 | | /// is the new allowance.
12 | | event Approval(address indexed owner, address indexed spender, uint256 value);
13 | |
14 | | /// @notice Returns the amount of tokens in existence.
15 | | function totalSupply() external view returns (uint256);
16 | |
17 | | /// @notice Returns the amount of tokens owned by `account`.
18 | | function balanceOf(address account) external view returns (uint256);
19 | |
20 | | /// @notice Moves `amount` tokens from the caller's account to `to`.
21 | | function transfer(address to, uint256 amount) external returns (bool);
22 | |
23 | | /// @notice Returns the remaining number of tokens that `spender` is allowed
24 | | /// to spend on behalf of `owner`
25 | | function allowance(address owner, address spender) external view returns (uint256);
26 | |
27 | | /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
28 | | /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
29 | | function approve(address spender, uint256 amount) external returns (bool);
30 | |
31 | | /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
32 | | /// `amount` is then deducted from the caller's allowance.
33 | | function transferFrom(address from, address to, uint256 amount) external returns (bool);
34 | |
35 | | /// @notice Returns the name of the token.
36 | | function name() external view returns (string memory);
37 | |
38 | | /// @notice Returns the symbol of the token.
39 | | function symbol() external view returns (string memory);
40 | |
41 | | /// @notice Returns the decimals places of the token.
42 | | function decimals() external view returns (uint8);
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC721.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2;
3 | |
4 | | import "./IERC165.sol";
5 | |
6 | | /// @title ERC-721 Non-Fungible Token Standard
7 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721
8 | | /// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
9 | | interface IERC721 is IERC165 {
10 | | /// @dev This emits when ownership of any NFT changes by any mechanism.
11 | | /// This event emits when NFTs are created (`from` == 0) and destroyed
12 | | /// (`to` == 0). Exception: during contract creation, any number of NFTs
13 | | /// may be created and assigned without emitting Transfer. At the time of
14 | | /// any transfer, the approved address for that NFT (if any) is reset to none.
15 | | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
16 | |
17 | | /// @dev This emits when the approved address for an NFT is changed or
18 | | /// reaffirmed. The zero address indicates there is no approved address.
19 | | /// When a Transfer event emits, this also indicates that the approved
20 | | /// address for that NFT (if any) is reset to none.
21 | | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
22 | |
23 | | /// @dev This emits when an operator is enabled or disabled for an owner.
24 | | /// The operator can manage all NFTs of the owner.
25 | | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
26 | |
27 | | /// @notice Count all NFTs assigned to an owner
28 | | /// @dev NFTs assigned to the zero address are considered invalid, and this
29 | | /// function throws for queries about the zero address.
30 | | /// @param _owner An address for whom to query the balance
31 | | /// @return The number of NFTs owned by `_owner`, possibly zero
32 | | function balanceOf(address _owner) external view returns (uint256);
33 | |
34 | | /// @notice Find the owner of an NFT
35 | | /// @dev NFTs assigned to zero address are considered invalid, and queries
36 | | /// about them do throw.
37 | | /// @param _tokenId The identifier for an NFT
38 | | /// @return The address of the owner of the NFT
39 | | function ownerOf(uint256 _tokenId) external view returns (address);
40 | |
41 | | /// @notice Transfers the ownership of an NFT from one address to another address
42 | | /// @dev Throws unless `msg.sender` is the current owner, an authorized
43 | | /// operator, or the approved address for this NFT. Throws if `_from` is
44 | | /// not the current owner. Throws if `_to` is the zero address. Throws if
45 | | /// `_tokenId` is not a valid NFT. When transfer is complete, this function
46 | | /// checks if `_to` is a smart contract (code size > 0). If so, it calls
47 | | /// `onERC721Received` on `_to` and throws if the return value is not
48 | | /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
49 | | /// @param _from The current owner of the NFT
50 | | /// @param _to The new owner
51 | | /// @param _tokenId The NFT to transfer
52 | | /// @param data Additional data with no specified format, sent in call to `_to`
53 | | function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
54 | |
55 | | /// @notice Transfers the ownership of an NFT from one address to another address
56 | | /// @dev This works identically to the other function with an extra data parameter,
57 | | /// except this function just sets data to "".
58 | | /// @param _from The current owner of the NFT
59 | | /// @param _to The new owner
60 | | /// @param _tokenId The NFT to transfer
61 | | function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
62 | |
63 | | /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
64 | | /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
65 | | /// THEY MAY BE PERMANENTLY LOST
66 | | /// @dev Throws unless `msg.sender` is the current owner, an authorized
67 | | /// operator, or the approved address for this NFT. Throws if `_from` is
68 | | /// not the current owner. Throws if `_to` is the zero address. Throws if
69 | | /// `_tokenId` is not a valid NFT.
70 | | /// @param _from The current owner of the NFT
71 | | /// @param _to The new owner
72 | | /// @param _tokenId The NFT to transfer
73 | | function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
74 | |
75 | | /// @notice Change or reaffirm the approved address for an NFT
76 | | /// @dev The zero address indicates there is no approved address.
77 | | /// Throws unless `msg.sender` is the current NFT owner, or an authorized
78 | | /// operator of the current owner.
79 | | /// @param _approved The new approved NFT controller
80 | | /// @param _tokenId The NFT to approve
81 | | function approve(address _approved, uint256 _tokenId) external payable;
82 | |
83 | | /// @notice Enable or disable approval for a third party ("operator") to manage
84 | | /// all of `msg.sender`'s assets
85 | | /// @dev Emits the ApprovalForAll event. The contract MUST allow
86 | | /// multiple operators per owner.
87 | | /// @param _operator Address to add to the set of authorized operators
88 | | /// @param _approved True if the operator is approved, false to revoke approval
89 | | function setApprovalForAll(address _operator, bool _approved) external;
90 | |
91 | | /// @notice Get the approved address for a single NFT
92 | | /// @dev Throws if `_tokenId` is not a valid NFT.
93 | | /// @param _tokenId The NFT to find the approved address for
94 | | /// @return The approved address for this NFT, or the zero address if there is none
95 | | function getApproved(uint256 _tokenId) external view returns (address);
96 | |
97 | | /// @notice Query if an address is an authorized operator for another address
98 | | /// @param _owner The address that owns the NFTs
99 | | /// @param _operator The address that acts on behalf of the owner
100 | | /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
101 | | function isApprovedForAll(address _owner, address _operator) external view returns (bool);
102 | | }
103 | |
104 | | /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
105 | | interface IERC721TokenReceiver {
106 | | /// @notice Handle the receipt of an NFT
107 | | /// @dev The ERC721 smart contract calls this function on the recipient
108 | | /// after a `transfer`. This function MAY throw to revert and reject the
109 | | /// transfer. Return of other than the magic value MUST result in the
110 | | /// transaction being reverted.
111 | | /// Note: the contract address is always the message sender.
112 | | /// @param _operator The address which called `safeTransferFrom` function
113 | | /// @param _from The address which previously owned the token
114 | | /// @param _tokenId The NFT identifier which is being transferred
115 | | /// @param _data Additional data with no specified format
116 | | /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
117 | | /// unless throwing
118 | | function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)
119 | | external
120 | | returns (bytes4);
121 | | }
122 | |
123 | | /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
124 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721
125 | | /// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
126 | | interface IERC721Metadata is IERC721 {
127 | | /// @notice A descriptive name for a collection of NFTs in this contract
128 | | function name() external view returns (string memory _name);
129 | |
130 | | /// @notice An abbreviated name for NFTs in this contract
131 | | function symbol() external view returns (string memory _symbol);
132 | |
133 | | /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
134 | | /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
135 | | /// 3986. The URI may point to a JSON file that conforms to the "ERC721
136 | | /// Metadata JSON Schema".
137 | | function tokenURI(uint256 _tokenId) external view returns (string memory);
138 | | }
139 | |
140 | | /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
141 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721
142 | | /// Note: the ERC-165 identifier for this interface is 0x780e9d63.
143 | | interface IERC721Enumerable is IERC721 {
144 | | /// @notice Count NFTs tracked by this contract
145 | | /// @return A count of valid NFTs tracked by this contract, where each one of
146 | | /// them has an assigned and queryable owner not equal to the zero address
147 | | function totalSupply() external view returns (uint256);
148 | |
149 | | /// @notice Enumerate valid NFTs
150 | | /// @dev Throws if `_index` >= `totalSupply()`.
151 | | /// @param _index A counter less than `totalSupply()`
152 | | /// @return The token identifier for the `_index`th NFT,
153 | | /// (sort order not specified)
154 | | function tokenByIndex(uint256 _index) external view returns (uint256);
155 | |
156 | | /// @notice Enumerate NFTs assigned to an owner
157 | | /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
158 | | /// `_owner` is the zero address, representing invalid NFTs.
159 | | /// @param _owner An address where we are interested in NFTs owned by them
160 | | /// @param _index A counter less than `balanceOf(_owner)`
161 | | /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
162 | | /// (sort order not specified)
163 | | function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
164 | | }
165 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IMulticall3.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | pragma experimental ABIEncoderV2;
5 | |
6 | | interface IMulticall3 {
7 | | struct Call {
8 | | address target;
9 | | bytes callData;
10 | | }
11 | |
12 | | struct Call3 {
13 | | address target;
14 | | bool allowFailure;
15 | | bytes callData;
16 | | }
17 | |
18 | | struct Call3Value {
19 | | address target;
20 | | bool allowFailure;
21 | | uint256 value;
22 | | bytes callData;
23 | | }
24 | |
25 | | struct Result {
26 | | bool success;
27 | | bytes returnData;
28 | | }
29 | |
30 | | function aggregate(Call[] calldata calls)
31 | | external
32 | | payable
33 | | returns (uint256 blockNumber, bytes[] memory returnData);
34 | |
35 | | function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
36 | |
37 | | function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
38 | |
39 | | function blockAndAggregate(Call[] calldata calls)
40 | | external
41 | | payable
42 | | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
43 | |
44 | | function getBasefee() external view returns (uint256 basefee);
45 | |
46 | | function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
47 | |
48 | | function getBlockNumber() external view returns (uint256 blockNumber);
49 | |
50 | | function getChainId() external view returns (uint256 chainid);
51 | |
52 | | function getCurrentBlockCoinbase() external view returns (address coinbase);
53 | |
54 | | function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
55 | |
56 | | function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
57 | |
58 | | function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
59 | |
60 | | function getEthBalance(address addr) external view returns (uint256 balance);
61 | |
62 | | function getLastBlockHash() external view returns (bytes32 blockHash);
63 | |
64 | | function tryAggregate(bool requireSuccess, Call[] calldata calls)
65 | | external
66 | | payable
67 | | returns (Result[] memory returnData);
68 | |
69 | | function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
70 | | external
71 | | payable
72 | | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
73 | | }
74 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/mocks/MockERC20.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | import {IERC20} from "../interfaces/IERC20.sol";
5 | |
6 | | /// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production.
7 | | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol
8 | | contract MockERC20 is IERC20 {
9 | | /*//////////////////////////////////////////////////////////////
10 | | METADATA STORAGE
11 | | //////////////////////////////////////////////////////////////*/
12 | |
13 | | string internal _name;
14 | |
15 | | string internal _symbol;
16 | |
17 | | uint8 internal _decimals;
18 | |
19 | | function name() external view override returns (string memory) {
20 | | return _name;
21 | | }
22 | |
23 | | function symbol() external view override returns (string memory) {
24 | | return _symbol;
25 | | }
26 | |
27 | | function decimals() external view override returns (uint8) {
28 | | return _decimals;
29 | | }
30 | |
31 | | /*//////////////////////////////////////////////////////////////
32 | | ERC20 STORAGE
33 | | //////////////////////////////////////////////////////////////*/
34 | |
35 | | uint256 internal _totalSupply;
36 | |
37 | | mapping(address => uint256) internal _balanceOf;
38 | |
39 | | mapping(address => mapping(address => uint256)) internal _allowance;
40 | |
41 | | function totalSupply() external view override returns (uint256) {
42 | | return _totalSupply;
43 | | }
44 | |
45 | | function balanceOf(address owner) external view override returns (uint256) {
46 | | return _balanceOf[owner];
47 | | }
48 | |
49 | | function allowance(address owner, address spender) external view override returns (uint256) {
50 | | return _allowance[owner][spender];
51 | | }
52 | |
53 | | /*//////////////////////////////////////////////////////////////
54 | | EIP-2612 STORAGE
55 | | //////////////////////////////////////////////////////////////*/
56 | |
57 | | uint256 internal INITIAL_CHAIN_ID;
58 | |
59 | | bytes32 internal INITIAL_DOMAIN_SEPARATOR;
60 | |
61 | | mapping(address => uint256) public nonces;
62 | |
63 | | /*//////////////////////////////////////////////////////////////
64 | | INITIALIZE
65 | | //////////////////////////////////////////////////////////////*/
66 | |
67 | | /// @dev A bool to track whether the contract has been initialized.
68 | | bool private initialized;
69 | |
70 | | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
71 | | /// syntaxes, we add an initialization function that can be called only once.
72 | | function initialize(string memory name_, string memory symbol_, uint8 decimals_) public {
73 | | require(!initialized, "ALREADY_INITIALIZED");
74 | |
75 | | _name = name_;
76 | | _symbol = symbol_;
77 | | _decimals = decimals_;
78 | |
79 | | INITIAL_CHAIN_ID = _pureChainId();
80 | | INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
81 | |
82 | | initialized = true;
83 | | }
84 | |
85 | | /*//////////////////////////////////////////////////////////////
86 | | ERC20 LOGIC
87 | | //////////////////////////////////////////////////////////////*/
88 | |
89 | | function approve(address spender, uint256 amount) public virtual override returns (bool) {
90 | | _allowance[msg.sender][spender] = amount;
91 | |
92 | | emit Approval(msg.sender, spender, amount);
93 | |
94 | | return true;
95 | | }
96 | |
97 | | function transfer(address to, uint256 amount) public virtual override returns (bool) {
98 | | _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount);
99 | | _balanceOf[to] = _add(_balanceOf[to], amount);
100 | |
101 | | emit Transfer(msg.sender, to, amount);
102 | |
103 | | return true;
104 | | }
105 | |
106 | | function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
107 | | uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals.
108 | |
109 | | if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount);
110 | |
111 | | _balanceOf[from] = _sub(_balanceOf[from], amount);
112 | | _balanceOf[to] = _add(_balanceOf[to], amount);
113 | |
114 | | emit Transfer(from, to, amount);
115 | |
116 | | return true;
117 | | }
118 | |
119 | | /*//////////////////////////////////////////////////////////////
120 | | EIP-2612 LOGIC
121 | | //////////////////////////////////////////////////////////////*/
122 | |
123 | | function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
124 | | public
125 | | virtual
126 | | {
127 | | require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
128 | |
129 | | address recoveredAddress = ecrecover(
130 | | keccak256(
131 | | abi.encodePacked(
132 | | "\x19\x01",
133 | | DOMAIN_SEPARATOR(),
134 | | keccak256(
135 | | abi.encode(
136 | | keccak256(
137 | | "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
138 | | ),
139 | | owner,
140 | | spender,
141 | | value,
142 | | nonces[owner]++,
143 | | deadline
144 | | )
145 | | )
146 | | )
147 | | ),
148 | | v,
149 | | r,
150 | | s
151 | | );
152 | |
153 | | require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
154 | |
155 | | _allowance[recoveredAddress][spender] = value;
156 | |
157 | | emit Approval(owner, spender, value);
158 | | }
159 | |
160 | | function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
161 | | return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
162 | | }
163 | |
164 | | function computeDomainSeparator() internal view virtual returns (bytes32) {
165 | | return keccak256(
166 | | abi.encode(
167 | | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
168 | | keccak256(bytes(_name)),
169 | | keccak256("1"),
170 | | _pureChainId(),
171 | | address(this)
172 | | )
173 | | );
174 | | }
175 | |
176 | | /*//////////////////////////////////////////////////////////////
177 | | INTERNAL MINT/BURN LOGIC
178 | | //////////////////////////////////////////////////////////////*/
179 | |
180 | | function _mint(address to, uint256 amount) internal virtual {
181 | | _totalSupply = _add(_totalSupply, amount);
182 | | _balanceOf[to] = _add(_balanceOf[to], amount);
183 | |
184 | | emit Transfer(address(0), to, amount);
185 | | }
186 | |
187 | | function _burn(address from, uint256 amount) internal virtual {
188 | | _balanceOf[from] = _sub(_balanceOf[from], amount);
189 | | _totalSupply = _sub(_totalSupply, amount);
190 | |
191 | | emit Transfer(from, address(0), amount);
192 | | }
193 | |
194 | | /*//////////////////////////////////////////////////////////////
195 | | INTERNAL SAFE MATH LOGIC
196 | | //////////////////////////////////////////////////////////////*/
197 | |
198 | | function _add(uint256 a, uint256 b) internal pure returns (uint256) {
199 | | uint256 c = a + b;
200 | | require(c >= a, "ERC20: addition overflow");
201 | | return c;
202 | | }
203 | |
204 | | function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
205 | | require(a >= b, "ERC20: subtraction underflow");
206 | | return a - b;
207 | | }
208 | |
209 | | /*//////////////////////////////////////////////////////////////
210 | | HELPERS
211 | | //////////////////////////////////////////////////////////////*/
212 | |
213 | | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
214 | | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
215 | | // can't simply access the chain ID in a normal view or pure function because the solc View Pure
216 | | // Checker changed `chainid` from pure to view in 0.8.0.
217 | | function _viewChainId() private view returns (uint256 chainId) {
218 | | // Assembly required since `block.chainid` was introduced in 0.8.0.
219 | | assembly {
220 | | chainId := chainid()
221 | | }
222 | |
223 | | address(this); // Silence warnings in older Solc versions.
224 | | }
225 | |
226 | | function _pureChainId() private pure returns (uint256 chainId) {
227 | | function() internal view returns (uint256) fnIn = _viewChainId;
228 | | function() internal pure returns (uint256) pureChainId;
229 | | assembly {
230 | | pureChainId := fnIn
231 | | }
232 | | chainId = pureChainId();
233 | | }
234 | | }
235 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/mocks/MockERC721.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol";
5 | |
6 | | /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production.
7 | | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol
8 | | contract MockERC721 is IERC721Metadata {
9 | | /*//////////////////////////////////////////////////////////////
10 | | METADATA STORAGE/LOGIC
11 | | //////////////////////////////////////////////////////////////*/
12 | |
13 | | string internal _name;
14 | |
15 | | string internal _symbol;
16 | |
17 | | function name() external view override returns (string memory) {
18 | | return _name;
19 | | }
20 | |
21 | | function symbol() external view override returns (string memory) {
22 | | return _symbol;
23 | | }
24 | |
25 | | function tokenURI(uint256 id) public view virtual override returns (string memory) {}
26 | |
27 | | /*//////////////////////////////////////////////////////////////
28 | | ERC721 BALANCE/OWNER STORAGE
29 | | //////////////////////////////////////////////////////////////*/
30 | |
31 | | mapping(uint256 => address) internal _ownerOf;
32 | |
33 | | mapping(address => uint256) internal _balanceOf;
34 | |
35 | | function ownerOf(uint256 id) public view virtual override returns (address owner) {
36 | | require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
37 | | }
38 | |
39 | | function balanceOf(address owner) public view virtual override returns (uint256) {
40 | | require(owner != address(0), "ZERO_ADDRESS");
41 | |
42 | | return _balanceOf[owner];
43 | | }
44 | |
45 | | /*//////////////////////////////////////////////////////////////
46 | | ERC721 APPROVAL STORAGE
47 | | //////////////////////////////////////////////////////////////*/
48 | |
49 | | mapping(uint256 => address) internal _getApproved;
50 | |
51 | | mapping(address => mapping(address => bool)) internal _isApprovedForAll;
52 | |
53 | | function getApproved(uint256 id) public view virtual override returns (address) {
54 | | return _getApproved[id];
55 | | }
56 | |
57 | | function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
58 | | return _isApprovedForAll[owner][operator];
59 | | }
60 | |
61 | | /*//////////////////////////////////////////////////////////////
62 | | INITIALIZE
63 | | //////////////////////////////////////////////////////////////*/
64 | |
65 | | /// @dev A bool to track whether the contract has been initialized.
66 | | bool private initialized;
67 | |
68 | | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
69 | | /// syntaxes, we add an initialization function that can be called only once.
70 | | function initialize(string memory name_, string memory symbol_) public {
71 | | require(!initialized, "ALREADY_INITIALIZED");
72 | |
73 | | _name = name_;
74 | | _symbol = symbol_;
75 | |
76 | | initialized = true;
77 | | }
78 | |
79 | | /*//////////////////////////////////////////////////////////////
80 | | ERC721 LOGIC
81 | | //////////////////////////////////////////////////////////////*/
82 | |
83 | | function approve(address spender, uint256 id) public payable virtual override {
84 | | address owner = _ownerOf[id];
85 | |
86 | | require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
87 | |
88 | | _getApproved[id] = spender;
89 | |
90 | | emit Approval(owner, spender, id);
91 | | }
92 | |
93 | | function setApprovalForAll(address operator, bool approved) public virtual override {
94 | | _isApprovedForAll[msg.sender][operator] = approved;
95 | |
96 | | emit ApprovalForAll(msg.sender, operator, approved);
97 | | }
98 | |
99 | | function transferFrom(address from, address to, uint256 id) public payable virtual override {
100 | | require(from == _ownerOf[id], "WRONG_FROM");
101 | |
102 | | require(to != address(0), "INVALID_RECIPIENT");
103 | |
104 | | require(
105 | | msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id],
106 | | "NOT_AUTHORIZED"
107 | | );
108 | |
109 | | // Underflow of the sender's balance is impossible because we check for
110 | | // ownership above and the recipient's balance can't realistically overflow.
111 | | _balanceOf[from]--;
112 | |
113 | | _balanceOf[to]++;
114 | |
115 | | _ownerOf[id] = to;
116 | |
117 | | delete _getApproved[id];
118 | |
119 | | emit Transfer(from, to, id);
120 | | }
121 | |
122 | | function safeTransferFrom(address from, address to, uint256 id) public payable virtual override {
123 | | transferFrom(from, to, id);
124 | |
125 | | require(
126 | | !_isContract(to)
127 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "")
128 | | == IERC721TokenReceiver.onERC721Received.selector,
129 | | "UNSAFE_RECIPIENT"
130 | | );
131 | | }
132 | |
133 | | function safeTransferFrom(address from, address to, uint256 id, bytes memory data)
134 | | public
135 | | payable
136 | | virtual
137 | | override
138 | | {
139 | | transferFrom(from, to, id);
140 | |
141 | | require(
142 | | !_isContract(to)
143 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
144 | | == IERC721TokenReceiver.onERC721Received.selector,
145 | | "UNSAFE_RECIPIENT"
146 | | );
147 | | }
148 | |
149 | | /*//////////////////////////////////////////////////////////////
150 | | ERC165 LOGIC
151 | | //////////////////////////////////////////////////////////////*/
152 | |
153 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
154 | | return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
155 | | || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721
156 | | || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
157 | | }
158 | |
159 | | /*//////////////////////////////////////////////////////////////
160 | | INTERNAL MINT/BURN LOGIC
161 | | //////////////////////////////////////////////////////////////*/
162 | |
163 | | function _mint(address to, uint256 id) internal virtual {
164 | | require(to != address(0), "INVALID_RECIPIENT");
165 | |
166 | | require(_ownerOf[id] == address(0), "ALREADY_MINTED");
167 | |
168 | | // Counter overflow is incredibly unrealistic.
169 | |
170 | | _balanceOf[to]++;
171 | |
172 | | _ownerOf[id] = to;
173 | |
174 | | emit Transfer(address(0), to, id);
175 | | }
176 | |
177 | | function _burn(uint256 id) internal virtual {
178 | | address owner = _ownerOf[id];
179 | |
180 | | require(owner != address(0), "NOT_MINTED");
181 | |
182 | | _balanceOf[owner]--;
183 | |
184 | | delete _ownerOf[id];
185 | |
186 | | delete _getApproved[id];
187 | |
188 | | emit Transfer(owner, address(0), id);
189 | | }
190 | |
191 | | /*//////////////////////////////////////////////////////////////
192 | | INTERNAL SAFE MINT LOGIC
193 | | //////////////////////////////////////////////////////////////*/
194 | |
195 | | function _safeMint(address to, uint256 id) internal virtual {
196 | | _mint(to, id);
197 | |
198 | | require(
199 | | !_isContract(to)
200 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "")
201 | | == IERC721TokenReceiver.onERC721Received.selector,
202 | | "UNSAFE_RECIPIENT"
203 | | );
204 | | }
205 | |
206 | | function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
207 | | _mint(to, id);
208 | |
209 | | require(
210 | | !_isContract(to)
211 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data)
212 | | == IERC721TokenReceiver.onERC721Received.selector,
213 | | "UNSAFE_RECIPIENT"
214 | | );
215 | | }
216 | |
217 | | /*//////////////////////////////////////////////////////////////
218 | | HELPERS
219 | | //////////////////////////////////////////////////////////////*/
220 | |
221 | | function _isContract(address _addr) private view returns (bool) {
222 | | uint256 codeLength;
223 | |
224 | | // Assembly required for versions < 0.8.0 to check extcodesize.
225 | | assembly {
226 | | codeLength := extcodesize(_addr)
227 | | }
228 | |
229 | | return codeLength > 0;
230 | | }
231 | | }
232 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/safeconsole.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity >=0.6.2 <0.9.0;
3 | |
4 | | /// @author philogy <https://github.com/philogy>
5 | | /// @dev Code generated automatically by script.
6 | * | library safeconsole {
7 | | uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
8 | |
9 | | // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
10 | | // for the view-to-pure log trick.
11 | | function _sendLogPayload(uint256 offset, uint256 size) private pure {
12 | | function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
13 | | function(uint256, uint256) internal pure pureSendLogPayload;
14 | | /// @solidity memory-safe-assembly
15 | | assembly {
16 | | pureSendLogPayload := fnIn
17 | | }
18 | | pureSendLogPayload(offset, size);
19 | | }
20 | |
21 | | function _sendLogPayloadView(uint256 offset, uint256 size) private view {
22 | | /// @solidity memory-safe-assembly
23 | | assembly {
24 | | pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
25 | | }
26 | | }
27 | |
28 | | function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
29 | | function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
30 | | function(uint256, uint256, uint256) internal pure pureMemcopy;
31 | | /// @solidity memory-safe-assembly
32 | | assembly {
33 | | pureMemcopy := fnIn
34 | | }
35 | | pureMemcopy(fromOffset, toOffset, length);
36 | | }
37 | |
38 | | function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
39 | | /// @solidity memory-safe-assembly
40 | | assembly {
41 | | pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
42 | | }
43 | | }
44 | |
45 | | function logMemory(uint256 offset, uint256 length) internal pure {
46 | | if (offset >= 0x60) {
47 | | // Sufficient memory before slice to prepare call header.
48 | | bytes32 m0;
49 | | bytes32 m1;
50 | | bytes32 m2;
51 | | /// @solidity memory-safe-assembly
52 | | assembly {
53 | | m0 := mload(sub(offset, 0x60))
54 | | m1 := mload(sub(offset, 0x40))
55 | | m2 := mload(sub(offset, 0x20))
56 | | // Selector of `log(bytes)`.
57 | | mstore(sub(offset, 0x60), 0x0be77f56)
58 | | mstore(sub(offset, 0x40), 0x20)
59 | | mstore(sub(offset, 0x20), length)
60 | | }
61 | | _sendLogPayload(offset - 0x44, length + 0x44);
62 | | /// @solidity memory-safe-assembly
63 | | assembly {
64 | | mstore(sub(offset, 0x60), m0)
65 | | mstore(sub(offset, 0x40), m1)
66 | | mstore(sub(offset, 0x20), m2)
67 | | }
68 | | } else {
69 | | // Insufficient space, so copy slice forward, add header and reverse.
70 | | bytes32 m0;
71 | | bytes32 m1;
72 | | bytes32 m2;
73 | | uint256 endOffset = offset + length;
74 | | /// @solidity memory-safe-assembly
75 | | assembly {
76 | | m0 := mload(add(endOffset, 0x00))
77 | | m1 := mload(add(endOffset, 0x20))
78 | | m2 := mload(add(endOffset, 0x40))
79 | | }
80 | | _memcopy(offset, offset + 0x60, length);
81 | | /// @solidity memory-safe-assembly
82 | | assembly {
83 | | // Selector of `log(bytes)`.
84 | | mstore(add(offset, 0x00), 0x0be77f56)
85 | | mstore(add(offset, 0x20), 0x20)
86 | | mstore(add(offset, 0x40), length)
87 | | }
88 | | _sendLogPayload(offset + 0x1c, length + 0x44);
89 | | _memcopy(offset + 0x60, offset, length);
90 | | /// @solidity memory-safe-assembly
91 | | assembly {
92 | | mstore(add(endOffset, 0x00), m0)
93 | | mstore(add(endOffset, 0x20), m1)
94 | | mstore(add(endOffset, 0x40), m2)
95 | | }
96 | | }
97 | | }
98 | |
99 | | function log(address p0) internal pure {
100 | | bytes32 m0;
101 | | bytes32 m1;
102 | | /// @solidity memory-safe-assembly
103 | | assembly {
104 | | m0 := mload(0x00)
105 | | m1 := mload(0x20)
106 | | // Selector of `log(address)`.
107 | | mstore(0x00, 0x2c2ecbc2)
108 | | mstore(0x20, p0)
109 | | }
110 | | _sendLogPayload(0x1c, 0x24);
111 | | /// @solidity memory-safe-assembly
112 | | assembly {
113 | | mstore(0x00, m0)
114 | | mstore(0x20, m1)
115 | | }
116 | | }
117 | |
118 | | function log(bool p0) internal pure {
119 | | bytes32 m0;
120 | | bytes32 m1;
121 | | /// @solidity memory-safe-assembly
122 | | assembly {
123 | | m0 := mload(0x00)
124 | | m1 := mload(0x20)
125 | | // Selector of `log(bool)`.
126 | | mstore(0x00, 0x32458eed)
127 | | mstore(0x20, p0)
128 | | }
129 | | _sendLogPayload(0x1c, 0x24);
130 | | /// @solidity memory-safe-assembly
131 | | assembly {
132 | | mstore(0x00, m0)
133 | | mstore(0x20, m1)
134 | | }
135 | | }
136 | |
137 | | function log(uint256 p0) internal pure {
138 | | bytes32 m0;
139 | | bytes32 m1;
140 | | /// @solidity memory-safe-assembly
141 | | assembly {
142 | | m0 := mload(0x00)
143 | | m1 := mload(0x20)
144 | | // Selector of `log(uint256)`.
145 | | mstore(0x00, 0xf82c50f1)
146 | | mstore(0x20, p0)
147 | | }
148 | | _sendLogPayload(0x1c, 0x24);
149 | | /// @solidity memory-safe-assembly
150 | | assembly {
151 | | mstore(0x00, m0)
152 | | mstore(0x20, m1)
153 | | }
154 | | }
155 | |
156 | | function log(bytes32 p0) internal pure {
157 | | bytes32 m0;
158 | | bytes32 m1;
159 | | bytes32 m2;
160 | | bytes32 m3;
161 | | /// @solidity memory-safe-assembly
162 | | assembly {
163 | | function writeString(pos, w) {
164 | | let length := 0
165 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
166 | | mstore(pos, length)
167 | | let shift := sub(256, shl(3, length))
168 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
169 | | }
170 | | m0 := mload(0x00)
171 | | m1 := mload(0x20)
172 | | m2 := mload(0x40)
173 | | m3 := mload(0x60)
174 | | // Selector of `log(string)`.
175 | | mstore(0x00, 0x41304fac)
176 | | mstore(0x20, 0x20)
177 | | writeString(0x40, p0)
178 | | }
179 | | _sendLogPayload(0x1c, 0x64);
180 | | /// @solidity memory-safe-assembly
181 | | assembly {
182 | | mstore(0x00, m0)
183 | | mstore(0x20, m1)
184 | | mstore(0x40, m2)
185 | | mstore(0x60, m3)
186 | | }
187 | | }
188 | |
189 | | function log(address p0, address p1) internal pure {
190 | | bytes32 m0;
191 | | bytes32 m1;
192 | | bytes32 m2;
193 | | /// @solidity memory-safe-assembly
194 | | assembly {
195 | | m0 := mload(0x00)
196 | | m1 := mload(0x20)
197 | | m2 := mload(0x40)
198 | | // Selector of `log(address,address)`.
199 | | mstore(0x00, 0xdaf0d4aa)
200 | | mstore(0x20, p0)
201 | | mstore(0x40, p1)
202 | | }
203 | | _sendLogPayload(0x1c, 0x44);
204 | | /// @solidity memory-safe-assembly
205 | | assembly {
206 | | mstore(0x00, m0)
207 | | mstore(0x20, m1)
208 | | mstore(0x40, m2)
209 | | }
210 | | }
211 | |
212 | | function log(address p0, bool p1) internal pure {
213 | | bytes32 m0;
214 | | bytes32 m1;
215 | | bytes32 m2;
216 | | /// @solidity memory-safe-assembly
217 | | assembly {
218 | | m0 := mload(0x00)
219 | | m1 := mload(0x20)
220 | | m2 := mload(0x40)
221 | | // Selector of `log(address,bool)`.
222 | | mstore(0x00, 0x75b605d3)
223 | | mstore(0x20, p0)
224 | | mstore(0x40, p1)
225 | | }
226 | | _sendLogPayload(0x1c, 0x44);
227 | | /// @solidity memory-safe-assembly
228 | | assembly {
229 | | mstore(0x00, m0)
230 | | mstore(0x20, m1)
231 | | mstore(0x40, m2)
232 | | }
233 | | }
234 | |
235 | | function log(address p0, uint256 p1) internal pure {
236 | | bytes32 m0;
237 | | bytes32 m1;
238 | | bytes32 m2;
239 | | /// @solidity memory-safe-assembly
240 | | assembly {
241 | | m0 := mload(0x00)
242 | | m1 := mload(0x20)
243 | | m2 := mload(0x40)
244 | | // Selector of `log(address,uint256)`.
245 | | mstore(0x00, 0x8309e8a8)
246 | | mstore(0x20, p0)
247 | | mstore(0x40, p1)
248 | | }
249 | | _sendLogPayload(0x1c, 0x44);
250 | | /// @solidity memory-safe-assembly
251 | | assembly {
252 | | mstore(0x00, m0)
253 | | mstore(0x20, m1)
254 | | mstore(0x40, m2)
255 | | }
256 | | }
257 | |
258 | | function log(address p0, bytes32 p1) internal pure {
259 | | bytes32 m0;
260 | | bytes32 m1;
261 | | bytes32 m2;
262 | | bytes32 m3;
263 | | bytes32 m4;
264 | | /// @solidity memory-safe-assembly
265 | | assembly {
266 | | function writeString(pos, w) {
267 | | let length := 0
268 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
269 | | mstore(pos, length)
270 | | let shift := sub(256, shl(3, length))
271 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
272 | | }
273 | | m0 := mload(0x00)
274 | | m1 := mload(0x20)
275 | | m2 := mload(0x40)
276 | | m3 := mload(0x60)
277 | | m4 := mload(0x80)
278 | | // Selector of `log(address,string)`.
279 | | mstore(0x00, 0x759f86bb)
280 | | mstore(0x20, p0)
281 | | mstore(0x40, 0x40)
282 | | writeString(0x60, p1)
283 | | }
284 | | _sendLogPayload(0x1c, 0x84);
285 | | /// @solidity memory-safe-assembly
286 | | assembly {
287 | | mstore(0x00, m0)
288 | | mstore(0x20, m1)
289 | | mstore(0x40, m2)
290 | | mstore(0x60, m3)
291 | | mstore(0x80, m4)
292 | | }
293 | | }
294 | |
295 | | function log(bool p0, address p1) internal pure {
296 | | bytes32 m0;
297 | | bytes32 m1;
298 | | bytes32 m2;
299 | | /// @solidity memory-safe-assembly
300 | | assembly {
301 | | m0 := mload(0x00)
302 | | m1 := mload(0x20)
303 | | m2 := mload(0x40)
304 | | // Selector of `log(bool,address)`.
305 | | mstore(0x00, 0x853c4849)
306 | | mstore(0x20, p0)
307 | | mstore(0x40, p1)
308 | | }
309 | | _sendLogPayload(0x1c, 0x44);
310 | | /// @solidity memory-safe-assembly
311 | | assembly {
312 | | mstore(0x00, m0)
313 | | mstore(0x20, m1)
314 | | mstore(0x40, m2)
315 | | }
316 | | }
317 | |
318 | | function log(bool p0, bool p1) internal pure {
319 | | bytes32 m0;
320 | | bytes32 m1;
321 | | bytes32 m2;
322 | | /// @solidity memory-safe-assembly
323 | | assembly {
324 | | m0 := mload(0x00)
325 | | m1 := mload(0x20)
326 | | m2 := mload(0x40)
327 | | // Selector of `log(bool,bool)`.
328 | | mstore(0x00, 0x2a110e83)
329 | | mstore(0x20, p0)
330 | | mstore(0x40, p1)
331 | | }
332 | | _sendLogPayload(0x1c, 0x44);
333 | | /// @solidity memory-safe-assembly
334 | | assembly {
335 | | mstore(0x00, m0)
336 | | mstore(0x20, m1)
337 | | mstore(0x40, m2)
338 | | }
339 | | }
340 | |
341 | | function log(bool p0, uint256 p1) internal pure {
342 | | bytes32 m0;
343 | | bytes32 m1;
344 | | bytes32 m2;
345 | | /// @solidity memory-safe-assembly
346 | | assembly {
347 | | m0 := mload(0x00)
348 | | m1 := mload(0x20)
349 | | m2 := mload(0x40)
350 | | // Selector of `log(bool,uint256)`.
351 | | mstore(0x00, 0x399174d3)
352 | | mstore(0x20, p0)
353 | | mstore(0x40, p1)
354 | | }
355 | | _sendLogPayload(0x1c, 0x44);
356 | | /// @solidity memory-safe-assembly
357 | | assembly {
358 | | mstore(0x00, m0)
359 | | mstore(0x20, m1)
360 | | mstore(0x40, m2)
361 | | }
362 | | }
363 | |
364 | | function log(bool p0, bytes32 p1) internal pure {
365 | | bytes32 m0;
366 | | bytes32 m1;
367 | | bytes32 m2;
368 | | bytes32 m3;
369 | | bytes32 m4;
370 | | /// @solidity memory-safe-assembly
371 | | assembly {
372 | | function writeString(pos, w) {
373 | | let length := 0
374 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
375 | | mstore(pos, length)
376 | | let shift := sub(256, shl(3, length))
377 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
378 | | }
379 | | m0 := mload(0x00)
380 | | m1 := mload(0x20)
381 | | m2 := mload(0x40)
382 | | m3 := mload(0x60)
383 | | m4 := mload(0x80)
384 | | // Selector of `log(bool,string)`.
385 | | mstore(0x00, 0x8feac525)
386 | | mstore(0x20, p0)
387 | | mstore(0x40, 0x40)
388 | | writeString(0x60, p1)
389 | | }
390 | | _sendLogPayload(0x1c, 0x84);
391 | | /// @solidity memory-safe-assembly
392 | | assembly {
393 | | mstore(0x00, m0)
394 | | mstore(0x20, m1)
395 | | mstore(0x40, m2)
396 | | mstore(0x60, m3)
397 | | mstore(0x80, m4)
398 | | }
399 | | }
400 | |
401 | | function log(uint256 p0, address p1) internal pure {
402 | | bytes32 m0;
403 | | bytes32 m1;
404 | | bytes32 m2;
405 | | /// @solidity memory-safe-assembly
406 | | assembly {
407 | | m0 := mload(0x00)
408 | | m1 := mload(0x20)
409 | | m2 := mload(0x40)
410 | | // Selector of `log(uint256,address)`.
411 | | mstore(0x00, 0x69276c86)
412 | | mstore(0x20, p0)
413 | | mstore(0x40, p1)
414 | | }
415 | | _sendLogPayload(0x1c, 0x44);
416 | | /// @solidity memory-safe-assembly
417 | | assembly {
418 | | mstore(0x00, m0)
419 | | mstore(0x20, m1)
420 | | mstore(0x40, m2)
421 | | }
422 | | }
423 | |
424 | | function log(uint256 p0, bool p1) internal pure {
425 | | bytes32 m0;
426 | | bytes32 m1;
427 | | bytes32 m2;
428 | | /// @solidity memory-safe-assembly
429 | | assembly {
430 | | m0 := mload(0x00)
431 | | m1 := mload(0x20)
432 | | m2 := mload(0x40)
433 | | // Selector of `log(uint256,bool)`.
434 | | mstore(0x00, 0x1c9d7eb3)
435 | | mstore(0x20, p0)
436 | | mstore(0x40, p1)
437 | | }
438 | | _sendLogPayload(0x1c, 0x44);
439 | | /// @solidity memory-safe-assembly
440 | | assembly {
441 | | mstore(0x00, m0)
442 | | mstore(0x20, m1)
443 | | mstore(0x40, m2)
444 | | }
445 | | }
446 | |
447 | | function log(uint256 p0, uint256 p1) internal pure {
448 | | bytes32 m0;
449 | | bytes32 m1;
450 | | bytes32 m2;
451 | | /// @solidity memory-safe-assembly
452 | | assembly {
453 | | m0 := mload(0x00)
454 | | m1 := mload(0x20)
455 | | m2 := mload(0x40)
456 | | // Selector of `log(uint256,uint256)`.
457 | | mstore(0x00, 0xf666715a)
458 | | mstore(0x20, p0)
459 | | mstore(0x40, p1)
460 | | }
461 | | _sendLogPayload(0x1c, 0x44);
462 | | /// @solidity memory-safe-assembly
463 | | assembly {
464 | | mstore(0x00, m0)
465 | | mstore(0x20, m1)
466 | | mstore(0x40, m2)
467 | | }
468 | | }
469 | |
470 | | function log(uint256 p0, bytes32 p1) internal pure {
471 | | bytes32 m0;
472 | | bytes32 m1;
473 | | bytes32 m2;
474 | | bytes32 m3;
475 | | bytes32 m4;
476 | | /// @solidity memory-safe-assembly
477 | | assembly {
478 | | function writeString(pos, w) {
479 | | let length := 0
480 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
481 | | mstore(pos, length)
482 | | let shift := sub(256, shl(3, length))
483 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
484 | | }
485 | | m0 := mload(0x00)
486 | | m1 := mload(0x20)
487 | | m2 := mload(0x40)
488 | | m3 := mload(0x60)
489 | | m4 := mload(0x80)
490 | | // Selector of `log(uint256,string)`.
491 | | mstore(0x00, 0x643fd0df)
492 | | mstore(0x20, p0)
493 | | mstore(0x40, 0x40)
494 | | writeString(0x60, p1)
495 | | }
496 | | _sendLogPayload(0x1c, 0x84);
497 | | /// @solidity memory-safe-assembly
498 | | assembly {
499 | | mstore(0x00, m0)
500 | | mstore(0x20, m1)
501 | | mstore(0x40, m2)
502 | | mstore(0x60, m3)
503 | | mstore(0x80, m4)
504 | | }
505 | | }
506 | |
507 | | function log(bytes32 p0, address p1) internal pure {
508 | | bytes32 m0;
509 | | bytes32 m1;
510 | | bytes32 m2;
511 | | bytes32 m3;
512 | | bytes32 m4;
513 | | /// @solidity memory-safe-assembly
514 | | assembly {
515 | | function writeString(pos, w) {
516 | | let length := 0
517 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
518 | | mstore(pos, length)
519 | | let shift := sub(256, shl(3, length))
520 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
521 | | }
522 | | m0 := mload(0x00)
523 | | m1 := mload(0x20)
524 | | m2 := mload(0x40)
525 | | m3 := mload(0x60)
526 | | m4 := mload(0x80)
527 | | // Selector of `log(string,address)`.
528 | | mstore(0x00, 0x319af333)
529 | | mstore(0x20, 0x40)
530 | | mstore(0x40, p1)
531 | | writeString(0x60, p0)
532 | | }
533 | | _sendLogPayload(0x1c, 0x84);
534 | | /// @solidity memory-safe-assembly
535 | | assembly {
536 | | mstore(0x00, m0)
537 | | mstore(0x20, m1)
538 | | mstore(0x40, m2)
539 | | mstore(0x60, m3)
540 | | mstore(0x80, m4)
541 | | }
542 | | }
543 | |
544 | | function log(bytes32 p0, bool p1) internal pure {
545 | | bytes32 m0;
546 | | bytes32 m1;
547 | | bytes32 m2;
548 | | bytes32 m3;
549 | | bytes32 m4;
550 | | /// @solidity memory-safe-assembly
551 | | assembly {
552 | | function writeString(pos, w) {
553 | | let length := 0
554 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
555 | | mstore(pos, length)
556 | | let shift := sub(256, shl(3, length))
557 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
558 | | }
559 | | m0 := mload(0x00)
560 | | m1 := mload(0x20)
561 | | m2 := mload(0x40)
562 | | m3 := mload(0x60)
563 | | m4 := mload(0x80)
564 | | // Selector of `log(string,bool)`.
565 | | mstore(0x00, 0xc3b55635)
566 | | mstore(0x20, 0x40)
567 | | mstore(0x40, p1)
568 | | writeString(0x60, p0)
569 | | }
570 | | _sendLogPayload(0x1c, 0x84);
571 | | /// @solidity memory-safe-assembly
572 | | assembly {
573 | | mstore(0x00, m0)
574 | | mstore(0x20, m1)
575 | | mstore(0x40, m2)
576 | | mstore(0x60, m3)
577 | | mstore(0x80, m4)
578 | | }
579 | | }
580 | |
581 | | function log(bytes32 p0, uint256 p1) internal pure {
582 | | bytes32 m0;
583 | | bytes32 m1;
584 | | bytes32 m2;
585 | | bytes32 m3;
586 | | bytes32 m4;
587 | | /// @solidity memory-safe-assembly
588 | | assembly {
589 | | function writeString(pos, w) {
590 | | let length := 0
591 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
592 | | mstore(pos, length)
593 | | let shift := sub(256, shl(3, length))
594 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
595 | | }
596 | | m0 := mload(0x00)
597 | | m1 := mload(0x20)
598 | | m2 := mload(0x40)
599 | | m3 := mload(0x60)
600 | | m4 := mload(0x80)
601 | | // Selector of `log(string,uint256)`.
602 | | mstore(0x00, 0xb60e72cc)
603 | | mstore(0x20, 0x40)
604 | | mstore(0x40, p1)
605 | | writeString(0x60, p0)
606 | | }
607 | | _sendLogPayload(0x1c, 0x84);
608 | | /// @solidity memory-safe-assembly
609 | | assembly {
610 | | mstore(0x00, m0)
611 | | mstore(0x20, m1)
612 | | mstore(0x40, m2)
613 | | mstore(0x60, m3)
614 | | mstore(0x80, m4)
615 | | }
616 | | }
617 | |
618 | | function log(bytes32 p0, bytes32 p1) internal pure {
619 | | bytes32 m0;
620 | | bytes32 m1;
621 | | bytes32 m2;
622 | | bytes32 m3;
623 | | bytes32 m4;
624 | | bytes32 m5;
625 | | bytes32 m6;
626 | | /// @solidity memory-safe-assembly
627 | | assembly {
628 | | function writeString(pos, w) {
629 | | let length := 0
630 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
631 | | mstore(pos, length)
632 | | let shift := sub(256, shl(3, length))
633 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
634 | | }
635 | | m0 := mload(0x00)
636 | | m1 := mload(0x20)
637 | | m2 := mload(0x40)
638 | | m3 := mload(0x60)
639 | | m4 := mload(0x80)
640 | | m5 := mload(0xa0)
641 | | m6 := mload(0xc0)
642 | | // Selector of `log(string,string)`.
643 | | mstore(0x00, 0x4b5c4277)
644 | | mstore(0x20, 0x40)
645 | | mstore(0x40, 0x80)
646 | | writeString(0x60, p0)
647 | | writeString(0xa0, p1)
648 | | }
649 | | _sendLogPayload(0x1c, 0xc4);
650 | | /// @solidity memory-safe-assembly
651 | | assembly {
652 | | mstore(0x00, m0)
653 | | mstore(0x20, m1)
654 | | mstore(0x40, m2)
655 | | mstore(0x60, m3)
656 | | mstore(0x80, m4)
657 | | mstore(0xa0, m5)
658 | | mstore(0xc0, m6)
659 | | }
660 | | }
661 | |
662 | | function log(address p0, address p1, address p2) internal pure {
663 | | bytes32 m0;
664 | | bytes32 m1;
665 | | bytes32 m2;
666 | | bytes32 m3;
667 | | /// @solidity memory-safe-assembly
668 | | assembly {
669 | | m0 := mload(0x00)
670 | | m1 := mload(0x20)
671 | | m2 := mload(0x40)
672 | | m3 := mload(0x60)
673 | | // Selector of `log(address,address,address)`.
674 | | mstore(0x00, 0x018c84c2)
675 | | mstore(0x20, p0)
676 | | mstore(0x40, p1)
677 | | mstore(0x60, p2)
678 | | }
679 | | _sendLogPayload(0x1c, 0x64);
680 | | /// @solidity memory-safe-assembly
681 | | assembly {
682 | | mstore(0x00, m0)
683 | | mstore(0x20, m1)
684 | | mstore(0x40, m2)
685 | | mstore(0x60, m3)
686 | | }
687 | | }
688 | |
689 | | function log(address p0, address p1, bool p2) internal pure {
690 | | bytes32 m0;
691 | | bytes32 m1;
692 | | bytes32 m2;
693 | | bytes32 m3;
694 | | /// @solidity memory-safe-assembly
695 | | assembly {
696 | | m0 := mload(0x00)
697 | | m1 := mload(0x20)
698 | | m2 := mload(0x40)
699 | | m3 := mload(0x60)
700 | | // Selector of `log(address,address,bool)`.
701 | | mstore(0x00, 0xf2a66286)
702 | | mstore(0x20, p0)
703 | | mstore(0x40, p1)
704 | | mstore(0x60, p2)
705 | | }
706 | | _sendLogPayload(0x1c, 0x64);
707 | | /// @solidity memory-safe-assembly
708 | | assembly {
709 | | mstore(0x00, m0)
710 | | mstore(0x20, m1)
711 | | mstore(0x40, m2)
712 | | mstore(0x60, m3)
713 | | }
714 | | }
715 | |
716 | | function log(address p0, address p1, uint256 p2) internal pure {
717 | | bytes32 m0;
718 | | bytes32 m1;
719 | | bytes32 m2;
720 | | bytes32 m3;
721 | | /// @solidity memory-safe-assembly
722 | | assembly {
723 | | m0 := mload(0x00)
724 | | m1 := mload(0x20)
725 | | m2 := mload(0x40)
726 | | m3 := mload(0x60)
727 | | // Selector of `log(address,address,uint256)`.
728 | | mstore(0x00, 0x17fe6185)
729 | | mstore(0x20, p0)
730 | | mstore(0x40, p1)
731 | | mstore(0x60, p2)
732 | | }
733 | | _sendLogPayload(0x1c, 0x64);
734 | | /// @solidity memory-safe-assembly
735 | | assembly {
736 | | mstore(0x00, m0)
737 | | mstore(0x20, m1)
738 | | mstore(0x40, m2)
739 | | mstore(0x60, m3)
740 | | }
741 | | }
742 | |
743 | | function log(address p0, address p1, bytes32 p2) internal pure {
744 | | bytes32 m0;
745 | | bytes32 m1;
746 | | bytes32 m2;
747 | | bytes32 m3;
748 | | bytes32 m4;
749 | | bytes32 m5;
750 | | /// @solidity memory-safe-assembly
751 | | assembly {
752 | | function writeString(pos, w) {
753 | | let length := 0
754 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
755 | | mstore(pos, length)
756 | | let shift := sub(256, shl(3, length))
757 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
758 | | }
759 | | m0 := mload(0x00)
760 | | m1 := mload(0x20)
761 | | m2 := mload(0x40)
762 | | m3 := mload(0x60)
763 | | m4 := mload(0x80)
764 | | m5 := mload(0xa0)
765 | | // Selector of `log(address,address,string)`.
766 | | mstore(0x00, 0x007150be)
767 | | mstore(0x20, p0)
768 | | mstore(0x40, p1)
769 | | mstore(0x60, 0x60)
770 | | writeString(0x80, p2)
771 | | }
772 | | _sendLogPayload(0x1c, 0xa4);
773 | | /// @solidity memory-safe-assembly
774 | | assembly {
775 | | mstore(0x00, m0)
776 | | mstore(0x20, m1)
777 | | mstore(0x40, m2)
778 | | mstore(0x60, m3)
779 | | mstore(0x80, m4)
780 | | mstore(0xa0, m5)
781 | | }
782 | | }
783 | |
784 | | function log(address p0, bool p1, address p2) internal pure {
785 | | bytes32 m0;
786 | | bytes32 m1;
787 | | bytes32 m2;
788 | | bytes32 m3;
789 | | /// @solidity memory-safe-assembly
790 | | assembly {
791 | | m0 := mload(0x00)
792 | | m1 := mload(0x20)
793 | | m2 := mload(0x40)
794 | | m3 := mload(0x60)
795 | | // Selector of `log(address,bool,address)`.
796 | | mstore(0x00, 0xf11699ed)
797 | | mstore(0x20, p0)
798 | | mstore(0x40, p1)
799 | | mstore(0x60, p2)
800 | | }
801 | | _sendLogPayload(0x1c, 0x64);
802 | | /// @solidity memory-safe-assembly
803 | | assembly {
804 | | mstore(0x00, m0)
805 | | mstore(0x20, m1)
806 | | mstore(0x40, m2)
807 | | mstore(0x60, m3)
808 | | }
809 | | }
810 | |
811 | | function log(address p0, bool p1, bool p2) internal pure {
812 | | bytes32 m0;
813 | | bytes32 m1;
814 | | bytes32 m2;
815 | | bytes32 m3;
816 | | /// @solidity memory-safe-assembly
817 | | assembly {
818 | | m0 := mload(0x00)
819 | | m1 := mload(0x20)
820 | | m2 := mload(0x40)
821 | | m3 := mload(0x60)
822 | | // Selector of `log(address,bool,bool)`.
823 | | mstore(0x00, 0xeb830c92)
824 | | mstore(0x20, p0)
825 | | mstore(0x40, p1)
826 | | mstore(0x60, p2)
827 | | }
828 | | _sendLogPayload(0x1c, 0x64);
829 | | /// @solidity memory-safe-assembly
830 | | assembly {
831 | | mstore(0x00, m0)
832 | | mstore(0x20, m1)
833 | | mstore(0x40, m2)
834 | | mstore(0x60, m3)
835 | | }
836 | | }
837 | |
838 | | function log(address p0, bool p1, uint256 p2) internal pure {
839 | | bytes32 m0;
840 | | bytes32 m1;
841 | | bytes32 m2;
842 | | bytes32 m3;
843 | | /// @solidity memory-safe-assembly
844 | | assembly {
845 | | m0 := mload(0x00)
846 | | m1 := mload(0x20)
847 | | m2 := mload(0x40)
848 | | m3 := mload(0x60)
849 | | // Selector of `log(address,bool,uint256)`.
850 | | mstore(0x00, 0x9c4f99fb)
851 | | mstore(0x20, p0)
852 | | mstore(0x40, p1)
853 | | mstore(0x60, p2)
854 | | }
855 | | _sendLogPayload(0x1c, 0x64);
856 | | /// @solidity memory-safe-assembly
857 | | assembly {
858 | | mstore(0x00, m0)
859 | | mstore(0x20, m1)
860 | | mstore(0x40, m2)
861 | | mstore(0x60, m3)
862 | | }
863 | | }
864 | |
865 | | function log(address p0, bool p1, bytes32 p2) internal pure {
866 | | bytes32 m0;
867 | | bytes32 m1;
868 | | bytes32 m2;
869 | | bytes32 m3;
870 | | bytes32 m4;
871 | | bytes32 m5;
872 | | /// @solidity memory-safe-assembly
873 | | assembly {
874 | | function writeString(pos, w) {
875 | | let length := 0
876 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
877 | | mstore(pos, length)
878 | | let shift := sub(256, shl(3, length))
879 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
880 | | }
881 | | m0 := mload(0x00)
882 | | m1 := mload(0x20)
883 | | m2 := mload(0x40)
884 | | m3 := mload(0x60)
885 | | m4 := mload(0x80)
886 | | m5 := mload(0xa0)
887 | | // Selector of `log(address,bool,string)`.
888 | | mstore(0x00, 0x212255cc)
889 | | mstore(0x20, p0)
890 | | mstore(0x40, p1)
891 | | mstore(0x60, 0x60)
892 | | writeString(0x80, p2)
893 | | }
894 | | _sendLogPayload(0x1c, 0xa4);
895 | | /// @solidity memory-safe-assembly
896 | | assembly {
897 | | mstore(0x00, m0)
898 | | mstore(0x20, m1)
899 | | mstore(0x40, m2)
900 | | mstore(0x60, m3)
901 | | mstore(0x80, m4)
902 | | mstore(0xa0, m5)
903 | | }
904 | | }
905 | |
906 | | function log(address p0, uint256 p1, address p2) internal pure {
907 | | bytes32 m0;
908 | | bytes32 m1;
909 | | bytes32 m2;
910 | | bytes32 m3;
911 | | /// @solidity memory-safe-assembly
912 | | assembly {
913 | | m0 := mload(0x00)
914 | | m1 := mload(0x20)
915 | | m2 := mload(0x40)
916 | | m3 := mload(0x60)
917 | | // Selector of `log(address,uint256,address)`.
918 | | mstore(0x00, 0x7bc0d848)
919 | | mstore(0x20, p0)
920 | | mstore(0x40, p1)
921 | | mstore(0x60, p2)
922 | | }
923 | | _sendLogPayload(0x1c, 0x64);
924 | | /// @solidity memory-safe-assembly
925 | | assembly {
926 | | mstore(0x00, m0)
927 | | mstore(0x20, m1)
928 | | mstore(0x40, m2)
929 | | mstore(0x60, m3)
930 | | }
931 | | }
932 | |
933 | | function log(address p0, uint256 p1, bool p2) internal pure {
934 | | bytes32 m0;
935 | | bytes32 m1;
936 | | bytes32 m2;
937 | | bytes32 m3;
938 | | /// @solidity memory-safe-assembly
939 | | assembly {
940 | | m0 := mload(0x00)
941 | | m1 := mload(0x20)
942 | | m2 := mload(0x40)
943 | | m3 := mload(0x60)
944 | | // Selector of `log(address,uint256,bool)`.
945 | | mstore(0x00, 0x678209a8)
946 | | mstore(0x20, p0)
947 | | mstore(0x40, p1)
948 | | mstore(0x60, p2)
949 | | }
950 | | _sendLogPayload(0x1c, 0x64);
951 | | /// @solidity memory-safe-assembly
952 | | assembly {
953 | | mstore(0x00, m0)
954 | | mstore(0x20, m1)
955 | | mstore(0x40, m2)
956 | | mstore(0x60, m3)
957 | | }
958 | | }
959 | |
960 | | function log(address p0, uint256 p1, uint256 p2) internal pure {
961 | | bytes32 m0;
962 | | bytes32 m1;
963 | | bytes32 m2;
964 | | bytes32 m3;
965 | | /// @solidity memory-safe-assembly
966 | | assembly {
967 | | m0 := mload(0x00)
968 | | m1 := mload(0x20)
969 | | m2 := mload(0x40)
970 | | m3 := mload(0x60)
971 | | // Selector of `log(address,uint256,uint256)`.
972 | | mstore(0x00, 0xb69bcaf6)
973 | | mstore(0x20, p0)
974 | | mstore(0x40, p1)
975 | | mstore(0x60, p2)
976 | | }
977 | | _sendLogPayload(0x1c, 0x64);
978 | | /// @solidity memory-safe-assembly
979 | | assembly {
980 | | mstore(0x00, m0)
981 | | mstore(0x20, m1)
982 | | mstore(0x40, m2)
983 | | mstore(0x60, m3)
984 | | }
985 | | }
986 | |
987 | | function log(address p0, uint256 p1, bytes32 p2) internal pure {
988 | | bytes32 m0;
989 | | bytes32 m1;
990 | | bytes32 m2;
991 | | bytes32 m3;
992 | | bytes32 m4;
993 | | bytes32 m5;
994 | | /// @solidity memory-safe-assembly
995 | | assembly {
996 | | function writeString(pos, w) {
997 | | let length := 0
998 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
999 | | mstore(pos, length)
1000 | | let shift := sub(256, shl(3, length))
1001 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1002 | | }
1003 | | m0 := mload(0x00)
1004 | | m1 := mload(0x20)
1005 | | m2 := mload(0x40)
1006 | | m3 := mload(0x60)
1007 | | m4 := mload(0x80)
1008 | | m5 := mload(0xa0)
1009 | | // Selector of `log(address,uint256,string)`.
1010 | | mstore(0x00, 0xa1f2e8aa)
1011 | | mstore(0x20, p0)
1012 | | mstore(0x40, p1)
1013 | | mstore(0x60, 0x60)
1014 | | writeString(0x80, p2)
1015 | | }
1016 | | _sendLogPayload(0x1c, 0xa4);
1017 | | /// @solidity memory-safe-assembly
1018 | | assembly {
1019 | | mstore(0x00, m0)
1020 | | mstore(0x20, m1)
1021 | | mstore(0x40, m2)
1022 | | mstore(0x60, m3)
1023 | | mstore(0x80, m4)
1024 | | mstore(0xa0, m5)
1025 | | }
1026 | | }
1027 | |
1028 | | function log(address p0, bytes32 p1, address p2) internal pure {
1029 | | bytes32 m0;
1030 | | bytes32 m1;
1031 | | bytes32 m2;
1032 | | bytes32 m3;
1033 | | bytes32 m4;
1034 | | bytes32 m5;
1035 | | /// @solidity memory-safe-assembly
1036 | | assembly {
1037 | | function writeString(pos, w) {
1038 | | let length := 0
1039 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1040 | | mstore(pos, length)
1041 | | let shift := sub(256, shl(3, length))
1042 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1043 | | }
1044 | | m0 := mload(0x00)
1045 | | m1 := mload(0x20)
1046 | | m2 := mload(0x40)
1047 | | m3 := mload(0x60)
1048 | | m4 := mload(0x80)
1049 | | m5 := mload(0xa0)
1050 | | // Selector of `log(address,string,address)`.
1051 | | mstore(0x00, 0xf08744e8)
1052 | | mstore(0x20, p0)
1053 | | mstore(0x40, 0x60)
1054 | | mstore(0x60, p2)
1055 | | writeString(0x80, p1)
1056 | | }
1057 | | _sendLogPayload(0x1c, 0xa4);
1058 | | /// @solidity memory-safe-assembly
1059 | | assembly {
1060 | | mstore(0x00, m0)
1061 | | mstore(0x20, m1)
1062 | | mstore(0x40, m2)
1063 | | mstore(0x60, m3)
1064 | | mstore(0x80, m4)
1065 | | mstore(0xa0, m5)
1066 | | }
1067 | | }
1068 | |
1069 | | function log(address p0, bytes32 p1, bool p2) internal pure {
1070 | | bytes32 m0;
1071 | | bytes32 m1;
1072 | | bytes32 m2;
1073 | | bytes32 m3;
1074 | | bytes32 m4;
1075 | | bytes32 m5;
1076 | | /// @solidity memory-safe-assembly
1077 | | assembly {
1078 | | function writeString(pos, w) {
1079 | | let length := 0
1080 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1081 | | mstore(pos, length)
1082 | | let shift := sub(256, shl(3, length))
1083 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1084 | | }
1085 | | m0 := mload(0x00)
1086 | | m1 := mload(0x20)
1087 | | m2 := mload(0x40)
1088 | | m3 := mload(0x60)
1089 | | m4 := mload(0x80)
1090 | | m5 := mload(0xa0)
1091 | | // Selector of `log(address,string,bool)`.
1092 | | mstore(0x00, 0xcf020fb1)
1093 | | mstore(0x20, p0)
1094 | | mstore(0x40, 0x60)
1095 | | mstore(0x60, p2)
1096 | | writeString(0x80, p1)
1097 | | }
1098 | | _sendLogPayload(0x1c, 0xa4);
1099 | | /// @solidity memory-safe-assembly
1100 | | assembly {
1101 | | mstore(0x00, m0)
1102 | | mstore(0x20, m1)
1103 | | mstore(0x40, m2)
1104 | | mstore(0x60, m3)
1105 | | mstore(0x80, m4)
1106 | | mstore(0xa0, m5)
1107 | | }
1108 | | }
1109 | |
1110 | | function log(address p0, bytes32 p1, uint256 p2) internal pure {
1111 | | bytes32 m0;
1112 | | bytes32 m1;
1113 | | bytes32 m2;
1114 | | bytes32 m3;
1115 | | bytes32 m4;
1116 | | bytes32 m5;
1117 | | /// @solidity memory-safe-assembly
1118 | | assembly {
1119 | | function writeString(pos, w) {
1120 | | let length := 0
1121 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1122 | | mstore(pos, length)
1123 | | let shift := sub(256, shl(3, length))
1124 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1125 | | }
1126 | | m0 := mload(0x00)
1127 | | m1 := mload(0x20)
1128 | | m2 := mload(0x40)
1129 | | m3 := mload(0x60)
1130 | | m4 := mload(0x80)
1131 | | m5 := mload(0xa0)
1132 | | // Selector of `log(address,string,uint256)`.
1133 | | mstore(0x00, 0x67dd6ff1)
1134 | | mstore(0x20, p0)
1135 | | mstore(0x40, 0x60)
1136 | | mstore(0x60, p2)
1137 | | writeString(0x80, p1)
1138 | | }
1139 | | _sendLogPayload(0x1c, 0xa4);
1140 | | /// @solidity memory-safe-assembly
1141 | | assembly {
1142 | | mstore(0x00, m0)
1143 | | mstore(0x20, m1)
1144 | | mstore(0x40, m2)
1145 | | mstore(0x60, m3)
1146 | | mstore(0x80, m4)
1147 | | mstore(0xa0, m5)
1148 | | }
1149 | | }
1150 | |
1151 | | function log(address p0, bytes32 p1, bytes32 p2) internal pure {
1152 | | bytes32 m0;
1153 | | bytes32 m1;
1154 | | bytes32 m2;
1155 | | bytes32 m3;
1156 | | bytes32 m4;
1157 | | bytes32 m5;
1158 | | bytes32 m6;
1159 | | bytes32 m7;
1160 | | /// @solidity memory-safe-assembly
1161 | | assembly {
1162 | | function writeString(pos, w) {
1163 | | let length := 0
1164 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1165 | | mstore(pos, length)
1166 | | let shift := sub(256, shl(3, length))
1167 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1168 | | }
1169 | | m0 := mload(0x00)
1170 | | m1 := mload(0x20)
1171 | | m2 := mload(0x40)
1172 | | m3 := mload(0x60)
1173 | | m4 := mload(0x80)
1174 | | m5 := mload(0xa0)
1175 | | m6 := mload(0xc0)
1176 | | m7 := mload(0xe0)
1177 | | // Selector of `log(address,string,string)`.
1178 | | mstore(0x00, 0xfb772265)
1179 | | mstore(0x20, p0)
1180 | | mstore(0x40, 0x60)
1181 | | mstore(0x60, 0xa0)
1182 | | writeString(0x80, p1)
1183 | | writeString(0xc0, p2)
1184 | | }
1185 | | _sendLogPayload(0x1c, 0xe4);
1186 | | /// @solidity memory-safe-assembly
1187 | | assembly {
1188 | | mstore(0x00, m0)
1189 | | mstore(0x20, m1)
1190 | | mstore(0x40, m2)
1191 | | mstore(0x60, m3)
1192 | | mstore(0x80, m4)
1193 | | mstore(0xa0, m5)
1194 | | mstore(0xc0, m6)
1195 | | mstore(0xe0, m7)
1196 | | }
1197 | | }
1198 | |
1199 | | function log(bool p0, address p1, address p2) internal pure {
1200 | | bytes32 m0;
1201 | | bytes32 m1;
1202 | | bytes32 m2;
1203 | | bytes32 m3;
1204 | | /// @solidity memory-safe-assembly
1205 | | assembly {
1206 | | m0 := mload(0x00)
1207 | | m1 := mload(0x20)
1208 | | m2 := mload(0x40)
1209 | | m3 := mload(0x60)
1210 | | // Selector of `log(bool,address,address)`.
1211 | | mstore(0x00, 0xd2763667)
1212 | | mstore(0x20, p0)
1213 | | mstore(0x40, p1)
1214 | | mstore(0x60, p2)
1215 | | }
1216 | | _sendLogPayload(0x1c, 0x64);
1217 | | /// @solidity memory-safe-assembly
1218 | | assembly {
1219 | | mstore(0x00, m0)
1220 | | mstore(0x20, m1)
1221 | | mstore(0x40, m2)
1222 | | mstore(0x60, m3)
1223 | | }
1224 | | }
1225 | |
1226 | | function log(bool p0, address p1, bool p2) internal pure {
1227 | | bytes32 m0;
1228 | | bytes32 m1;
1229 | | bytes32 m2;
1230 | | bytes32 m3;
1231 | | /// @solidity memory-safe-assembly
1232 | | assembly {
1233 | | m0 := mload(0x00)
1234 | | m1 := mload(0x20)
1235 | | m2 := mload(0x40)
1236 | | m3 := mload(0x60)
1237 | | // Selector of `log(bool,address,bool)`.
1238 | | mstore(0x00, 0x18c9c746)
1239 | | mstore(0x20, p0)
1240 | | mstore(0x40, p1)
1241 | | mstore(0x60, p2)
1242 | | }
1243 | | _sendLogPayload(0x1c, 0x64);
1244 | | /// @solidity memory-safe-assembly
1245 | | assembly {
1246 | | mstore(0x00, m0)
1247 | | mstore(0x20, m1)
1248 | | mstore(0x40, m2)
1249 | | mstore(0x60, m3)
1250 | | }
1251 | | }
1252 | |
1253 | | function log(bool p0, address p1, uint256 p2) internal pure {
1254 | | bytes32 m0;
1255 | | bytes32 m1;
1256 | | bytes32 m2;
1257 | | bytes32 m3;
1258 | | /// @solidity memory-safe-assembly
1259 | | assembly {
1260 | | m0 := mload(0x00)
1261 | | m1 := mload(0x20)
1262 | | m2 := mload(0x40)
1263 | | m3 := mload(0x60)
1264 | | // Selector of `log(bool,address,uint256)`.
1265 | | mstore(0x00, 0x5f7b9afb)
1266 | | mstore(0x20, p0)
1267 | | mstore(0x40, p1)
1268 | | mstore(0x60, p2)
1269 | | }
1270 | | _sendLogPayload(0x1c, 0x64);
1271 | | /// @solidity memory-safe-assembly
1272 | | assembly {
1273 | | mstore(0x00, m0)
1274 | | mstore(0x20, m1)
1275 | | mstore(0x40, m2)
1276 | | mstore(0x60, m3)
1277 | | }
1278 | | }
1279 | |
1280 | | function log(bool p0, address p1, bytes32 p2) internal pure {
1281 | | bytes32 m0;
1282 | | bytes32 m1;
1283 | | bytes32 m2;
1284 | | bytes32 m3;
1285 | | bytes32 m4;
1286 | | bytes32 m5;
1287 | | /// @solidity memory-safe-assembly
1288 | | assembly {
1289 | | function writeString(pos, w) {
1290 | | let length := 0
1291 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1292 | | mstore(pos, length)
1293 | | let shift := sub(256, shl(3, length))
1294 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1295 | | }
1296 | | m0 := mload(0x00)
1297 | | m1 := mload(0x20)
1298 | | m2 := mload(0x40)
1299 | | m3 := mload(0x60)
1300 | | m4 := mload(0x80)
1301 | | m5 := mload(0xa0)
1302 | | // Selector of `log(bool,address,string)`.
1303 | | mstore(0x00, 0xde9a9270)
1304 | | mstore(0x20, p0)
1305 | | mstore(0x40, p1)
1306 | | mstore(0x60, 0x60)
1307 | | writeString(0x80, p2)
1308 | | }
1309 | | _sendLogPayload(0x1c, 0xa4);
1310 | | /// @solidity memory-safe-assembly
1311 | | assembly {
1312 | | mstore(0x00, m0)
1313 | | mstore(0x20, m1)
1314 | | mstore(0x40, m2)
1315 | | mstore(0x60, m3)
1316 | | mstore(0x80, m4)
1317 | | mstore(0xa0, m5)
1318 | | }
1319 | | }
1320 | |
1321 | | function log(bool p0, bool p1, address p2) internal pure {
1322 | | bytes32 m0;
1323 | | bytes32 m1;
1324 | | bytes32 m2;
1325 | | bytes32 m3;
1326 | | /// @solidity memory-safe-assembly
1327 | | assembly {
1328 | | m0 := mload(0x00)
1329 | | m1 := mload(0x20)
1330 | | m2 := mload(0x40)
1331 | | m3 := mload(0x60)
1332 | | // Selector of `log(bool,bool,address)`.
1333 | | mstore(0x00, 0x1078f68d)
1334 | | mstore(0x20, p0)
1335 | | mstore(0x40, p1)
1336 | | mstore(0x60, p2)
1337 | | }
1338 | | _sendLogPayload(0x1c, 0x64);
1339 | | /// @solidity memory-safe-assembly
1340 | | assembly {
1341 | | mstore(0x00, m0)
1342 | | mstore(0x20, m1)
1343 | | mstore(0x40, m2)
1344 | | mstore(0x60, m3)
1345 | | }
1346 | | }
1347 | |
1348 | | function log(bool p0, bool p1, bool p2) internal pure {
1349 | | bytes32 m0;
1350 | | bytes32 m1;
1351 | | bytes32 m2;
1352 | | bytes32 m3;
1353 | | /// @solidity memory-safe-assembly
1354 | | assembly {
1355 | | m0 := mload(0x00)
1356 | | m1 := mload(0x20)
1357 | | m2 := mload(0x40)
1358 | | m3 := mload(0x60)
1359 | | // Selector of `log(bool,bool,bool)`.
1360 | | mstore(0x00, 0x50709698)
1361 | | mstore(0x20, p0)
1362 | | mstore(0x40, p1)
1363 | | mstore(0x60, p2)
1364 | | }
1365 | | _sendLogPayload(0x1c, 0x64);
1366 | | /// @solidity memory-safe-assembly
1367 | | assembly {
1368 | | mstore(0x00, m0)
1369 | | mstore(0x20, m1)
1370 | | mstore(0x40, m2)
1371 | | mstore(0x60, m3)
1372 | | }
1373 | | }
1374 | |
1375 | | function log(bool p0, bool p1, uint256 p2) internal pure {
1376 | | bytes32 m0;
1377 | | bytes32 m1;
1378 | | bytes32 m2;
1379 | | bytes32 m3;
1380 | | /// @solidity memory-safe-assembly
1381 | | assembly {
1382 | | m0 := mload(0x00)
1383 | | m1 := mload(0x20)
1384 | | m2 := mload(0x40)
1385 | | m3 := mload(0x60)
1386 | | // Selector of `log(bool,bool,uint256)`.
1387 | | mstore(0x00, 0x12f21602)
1388 | | mstore(0x20, p0)
1389 | | mstore(0x40, p1)
1390 | | mstore(0x60, p2)
1391 | | }
1392 | | _sendLogPayload(0x1c, 0x64);
1393 | | /// @solidity memory-safe-assembly
1394 | | assembly {
1395 | | mstore(0x00, m0)
1396 | | mstore(0x20, m1)
1397 | | mstore(0x40, m2)
1398 | | mstore(0x60, m3)
1399 | | }
1400 | | }
1401 | |
1402 | | function log(bool p0, bool p1, bytes32 p2) internal pure {
1403 | | bytes32 m0;
1404 | | bytes32 m1;
1405 | | bytes32 m2;
1406 | | bytes32 m3;
1407 | | bytes32 m4;
1408 | | bytes32 m5;
1409 | | /// @solidity memory-safe-assembly
1410 | | assembly {
1411 | | function writeString(pos, w) {
1412 | | let length := 0
1413 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1414 | | mstore(pos, length)
1415 | | let shift := sub(256, shl(3, length))
1416 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1417 | | }
1418 | | m0 := mload(0x00)
1419 | | m1 := mload(0x20)
1420 | | m2 := mload(0x40)
1421 | | m3 := mload(0x60)
1422 | | m4 := mload(0x80)
1423 | | m5 := mload(0xa0)
1424 | | // Selector of `log(bool,bool,string)`.
1425 | | mstore(0x00, 0x2555fa46)
1426 | | mstore(0x20, p0)
1427 | | mstore(0x40, p1)
1428 | | mstore(0x60, 0x60)
1429 | | writeString(0x80, p2)
1430 | | }
1431 | | _sendLogPayload(0x1c, 0xa4);
1432 | | /// @solidity memory-safe-assembly
1433 | | assembly {
1434 | | mstore(0x00, m0)
1435 | | mstore(0x20, m1)
1436 | | mstore(0x40, m2)
1437 | | mstore(0x60, m3)
1438 | | mstore(0x80, m4)
1439 | | mstore(0xa0, m5)
1440 | | }
1441 | | }
1442 | |
1443 | | function log(bool p0, uint256 p1, address p2) internal pure {
1444 | | bytes32 m0;
1445 | | bytes32 m1;
1446 | | bytes32 m2;
1447 | | bytes32 m3;
1448 | | /// @solidity memory-safe-assembly
1449 | | assembly {
1450 | | m0 := mload(0x00)
1451 | | m1 := mload(0x20)
1452 | | m2 := mload(0x40)
1453 | | m3 := mload(0x60)
1454 | | // Selector of `log(bool,uint256,address)`.
1455 | | mstore(0x00, 0x088ef9d2)
1456 | | mstore(0x20, p0)
1457 | | mstore(0x40, p1)
1458 | | mstore(0x60, p2)
1459 | | }
1460 | | _sendLogPayload(0x1c, 0x64);
1461 | | /// @solidity memory-safe-assembly
1462 | | assembly {
1463 | | mstore(0x00, m0)
1464 | | mstore(0x20, m1)
1465 | | mstore(0x40, m2)
1466 | | mstore(0x60, m3)
1467 | | }
1468 | | }
1469 | |
1470 | | function log(bool p0, uint256 p1, bool p2) internal pure {
1471 | | bytes32 m0;
1472 | | bytes32 m1;
1473 | | bytes32 m2;
1474 | | bytes32 m3;
1475 | | /// @solidity memory-safe-assembly
1476 | | assembly {
1477 | | m0 := mload(0x00)
1478 | | m1 := mload(0x20)
1479 | | m2 := mload(0x40)
1480 | | m3 := mload(0x60)
1481 | | // Selector of `log(bool,uint256,bool)`.
1482 | | mstore(0x00, 0xe8defba9)
1483 | | mstore(0x20, p0)
1484 | | mstore(0x40, p1)
1485 | | mstore(0x60, p2)
1486 | | }
1487 | | _sendLogPayload(0x1c, 0x64);
1488 | | /// @solidity memory-safe-assembly
1489 | | assembly {
1490 | | mstore(0x00, m0)
1491 | | mstore(0x20, m1)
1492 | | mstore(0x40, m2)
1493 | | mstore(0x60, m3)
1494 | | }
1495 | | }
1496 | |
1497 | | function log(bool p0, uint256 p1, uint256 p2) internal pure {
1498 | | bytes32 m0;
1499 | | bytes32 m1;
1500 | | bytes32 m2;
1501 | | bytes32 m3;
1502 | | /// @solidity memory-safe-assembly
1503 | | assembly {
1504 | | m0 := mload(0x00)
1505 | | m1 := mload(0x20)
1506 | | m2 := mload(0x40)
1507 | | m3 := mload(0x60)
1508 | | // Selector of `log(bool,uint256,uint256)`.
1509 | | mstore(0x00, 0x37103367)
1510 | | mstore(0x20, p0)
1511 | | mstore(0x40, p1)
1512 | | mstore(0x60, p2)
1513 | | }
1514 | | _sendLogPayload(0x1c, 0x64);
1515 | | /// @solidity memory-safe-assembly
1516 | | assembly {
1517 | | mstore(0x00, m0)
1518 | | mstore(0x20, m1)
1519 | | mstore(0x40, m2)
1520 | | mstore(0x60, m3)
1521 | | }
1522 | | }
1523 | |
1524 | | function log(bool p0, uint256 p1, bytes32 p2) internal pure {
1525 | | bytes32 m0;
1526 | | bytes32 m1;
1527 | | bytes32 m2;
1528 | | bytes32 m3;
1529 | | bytes32 m4;
1530 | | bytes32 m5;
1531 | | /// @solidity memory-safe-assembly
1532 | | assembly {
1533 | | function writeString(pos, w) {
1534 | | let length := 0
1535 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1536 | | mstore(pos, length)
1537 | | let shift := sub(256, shl(3, length))
1538 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1539 | | }
1540 | | m0 := mload(0x00)
1541 | | m1 := mload(0x20)
1542 | | m2 := mload(0x40)
1543 | | m3 := mload(0x60)
1544 | | m4 := mload(0x80)
1545 | | m5 := mload(0xa0)
1546 | | // Selector of `log(bool,uint256,string)`.
1547 | | mstore(0x00, 0xc3fc3970)
1548 | | mstore(0x20, p0)
1549 | | mstore(0x40, p1)
1550 | | mstore(0x60, 0x60)
1551 | | writeString(0x80, p2)
1552 | | }
1553 | | _sendLogPayload(0x1c, 0xa4);
1554 | | /// @solidity memory-safe-assembly
1555 | | assembly {
1556 | | mstore(0x00, m0)
1557 | | mstore(0x20, m1)
1558 | | mstore(0x40, m2)
1559 | | mstore(0x60, m3)
1560 | | mstore(0x80, m4)
1561 | | mstore(0xa0, m5)
1562 | | }
1563 | | }
1564 | |
1565 | | function log(bool p0, bytes32 p1, address p2) internal pure {
1566 | | bytes32 m0;
1567 | | bytes32 m1;
1568 | | bytes32 m2;
1569 | | bytes32 m3;
1570 | | bytes32 m4;
1571 | | bytes32 m5;
1572 | | /// @solidity memory-safe-assembly
1573 | | assembly {
1574 | | function writeString(pos, w) {
1575 | | let length := 0
1576 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1577 | | mstore(pos, length)
1578 | | let shift := sub(256, shl(3, length))
1579 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1580 | | }
1581 | | m0 := mload(0x00)
1582 | | m1 := mload(0x20)
1583 | | m2 := mload(0x40)
1584 | | m3 := mload(0x60)
1585 | | m4 := mload(0x80)
1586 | | m5 := mload(0xa0)
1587 | | // Selector of `log(bool,string,address)`.
1588 | | mstore(0x00, 0x9591b953)
1589 | | mstore(0x20, p0)
1590 | | mstore(0x40, 0x60)
1591 | | mstore(0x60, p2)
1592 | | writeString(0x80, p1)
1593 | | }
1594 | | _sendLogPayload(0x1c, 0xa4);
1595 | | /// @solidity memory-safe-assembly
1596 | | assembly {
1597 | | mstore(0x00, m0)
1598 | | mstore(0x20, m1)
1599 | | mstore(0x40, m2)
1600 | | mstore(0x60, m3)
1601 | | mstore(0x80, m4)
1602 | | mstore(0xa0, m5)
1603 | | }
1604 | | }
1605 | |
1606 | | function log(bool p0, bytes32 p1, bool p2) internal pure {
1607 | | bytes32 m0;
1608 | | bytes32 m1;
1609 | | bytes32 m2;
1610 | | bytes32 m3;
1611 | | bytes32 m4;
1612 | | bytes32 m5;
1613 | | /// @solidity memory-safe-assembly
1614 | | assembly {
1615 | | function writeString(pos, w) {
1616 | | let length := 0
1617 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1618 | | mstore(pos, length)
1619 | | let shift := sub(256, shl(3, length))
1620 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1621 | | }
1622 | | m0 := mload(0x00)
1623 | | m1 := mload(0x20)
1624 | | m2 := mload(0x40)
1625 | | m3 := mload(0x60)
1626 | | m4 := mload(0x80)
1627 | | m5 := mload(0xa0)
1628 | | // Selector of `log(bool,string,bool)`.
1629 | | mstore(0x00, 0xdbb4c247)
1630 | | mstore(0x20, p0)
1631 | | mstore(0x40, 0x60)
1632 | | mstore(0x60, p2)
1633 | | writeString(0x80, p1)
1634 | | }
1635 | | _sendLogPayload(0x1c, 0xa4);
1636 | | /// @solidity memory-safe-assembly
1637 | | assembly {
1638 | | mstore(0x00, m0)
1639 | | mstore(0x20, m1)
1640 | | mstore(0x40, m2)
1641 | | mstore(0x60, m3)
1642 | | mstore(0x80, m4)
1643 | | mstore(0xa0, m5)
1644 | | }
1645 | | }
1646 | |
1647 | | function log(bool p0, bytes32 p1, uint256 p2) internal pure {
1648 | | bytes32 m0;
1649 | | bytes32 m1;
1650 | | bytes32 m2;
1651 | | bytes32 m3;
1652 | | bytes32 m4;
1653 | | bytes32 m5;
1654 | | /// @solidity memory-safe-assembly
1655 | | assembly {
1656 | | function writeString(pos, w) {
1657 | | let length := 0
1658 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1659 | | mstore(pos, length)
1660 | | let shift := sub(256, shl(3, length))
1661 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1662 | | }
1663 | | m0 := mload(0x00)
1664 | | m1 := mload(0x20)
1665 | | m2 := mload(0x40)
1666 | | m3 := mload(0x60)
1667 | | m4 := mload(0x80)
1668 | | m5 := mload(0xa0)
1669 | | // Selector of `log(bool,string,uint256)`.
1670 | | mstore(0x00, 0x1093ee11)
1671 | | mstore(0x20, p0)
1672 | | mstore(0x40, 0x60)
1673 | | mstore(0x60, p2)
1674 | | writeString(0x80, p1)
1675 | | }
1676 | | _sendLogPayload(0x1c, 0xa4);
1677 | | /// @solidity memory-safe-assembly
1678 | | assembly {
1679 | | mstore(0x00, m0)
1680 | | mstore(0x20, m1)
1681 | | mstore(0x40, m2)
1682 | | mstore(0x60, m3)
1683 | | mstore(0x80, m4)
1684 | | mstore(0xa0, m5)
1685 | | }
1686 | | }
1687 | |
1688 | | function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
1689 | | bytes32 m0;
1690 | | bytes32 m1;
1691 | | bytes32 m2;
1692 | | bytes32 m3;
1693 | | bytes32 m4;
1694 | | bytes32 m5;
1695 | | bytes32 m6;
1696 | | bytes32 m7;
1697 | | /// @solidity memory-safe-assembly
1698 | | assembly {
1699 | | function writeString(pos, w) {
1700 | | let length := 0
1701 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1702 | | mstore(pos, length)
1703 | | let shift := sub(256, shl(3, length))
1704 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1705 | | }
1706 | | m0 := mload(0x00)
1707 | | m1 := mload(0x20)
1708 | | m2 := mload(0x40)
1709 | | m3 := mload(0x60)
1710 | | m4 := mload(0x80)
1711 | | m5 := mload(0xa0)
1712 | | m6 := mload(0xc0)
1713 | | m7 := mload(0xe0)
1714 | | // Selector of `log(bool,string,string)`.
1715 | | mstore(0x00, 0xb076847f)
1716 | | mstore(0x20, p0)
1717 | | mstore(0x40, 0x60)
1718 | | mstore(0x60, 0xa0)
1719 | | writeString(0x80, p1)
1720 | | writeString(0xc0, p2)
1721 | | }
1722 | | _sendLogPayload(0x1c, 0xe4);
1723 | | /// @solidity memory-safe-assembly
1724 | | assembly {
1725 | | mstore(0x00, m0)
1726 | | mstore(0x20, m1)
1727 | | mstore(0x40, m2)
1728 | | mstore(0x60, m3)
1729 | | mstore(0x80, m4)
1730 | | mstore(0xa0, m5)
1731 | | mstore(0xc0, m6)
1732 | | mstore(0xe0, m7)
1733 | | }
1734 | | }
1735 | |
1736 | | function log(uint256 p0, address p1, address p2) internal pure {
1737 | | bytes32 m0;
1738 | | bytes32 m1;
1739 | | bytes32 m2;
1740 | | bytes32 m3;
1741 | | /// @solidity memory-safe-assembly
1742 | | assembly {
1743 | | m0 := mload(0x00)
1744 | | m1 := mload(0x20)
1745 | | m2 := mload(0x40)
1746 | | m3 := mload(0x60)
1747 | | // Selector of `log(uint256,address,address)`.
1748 | | mstore(0x00, 0xbcfd9be0)
1749 | | mstore(0x20, p0)
1750 | | mstore(0x40, p1)
1751 | | mstore(0x60, p2)
1752 | | }
1753 | | _sendLogPayload(0x1c, 0x64);
1754 | | /// @solidity memory-safe-assembly
1755 | | assembly {
1756 | | mstore(0x00, m0)
1757 | | mstore(0x20, m1)
1758 | | mstore(0x40, m2)
1759 | | mstore(0x60, m3)
1760 | | }
1761 | | }
1762 | |
1763 | | function log(uint256 p0, address p1, bool p2) internal pure {
1764 | | bytes32 m0;
1765 | | bytes32 m1;
1766 | | bytes32 m2;
1767 | | bytes32 m3;
1768 | | /// @solidity memory-safe-assembly
1769 | | assembly {
1770 | | m0 := mload(0x00)
1771 | | m1 := mload(0x20)
1772 | | m2 := mload(0x40)
1773 | | m3 := mload(0x60)
1774 | | // Selector of `log(uint256,address,bool)`.
1775 | | mstore(0x00, 0x9b6ec042)
1776 | | mstore(0x20, p0)
1777 | | mstore(0x40, p1)
1778 | | mstore(0x60, p2)
1779 | | }
1780 | | _sendLogPayload(0x1c, 0x64);
1781 | | /// @solidity memory-safe-assembly
1782 | | assembly {
1783 | | mstore(0x00, m0)
1784 | | mstore(0x20, m1)
1785 | | mstore(0x40, m2)
1786 | | mstore(0x60, m3)
1787 | | }
1788 | | }
1789 | |
1790 | | function log(uint256 p0, address p1, uint256 p2) internal pure {
1791 | | bytes32 m0;
1792 | | bytes32 m1;
1793 | | bytes32 m2;
1794 | | bytes32 m3;
1795 | | /// @solidity memory-safe-assembly
1796 | | assembly {
1797 | | m0 := mload(0x00)
1798 | | m1 := mload(0x20)
1799 | | m2 := mload(0x40)
1800 | | m3 := mload(0x60)
1801 | | // Selector of `log(uint256,address,uint256)`.
1802 | | mstore(0x00, 0x5a9b5ed5)
1803 | | mstore(0x20, p0)
1804 | | mstore(0x40, p1)
1805 | | mstore(0x60, p2)
1806 | | }
1807 | | _sendLogPayload(0x1c, 0x64);
1808 | | /// @solidity memory-safe-assembly
1809 | | assembly {
1810 | | mstore(0x00, m0)
1811 | | mstore(0x20, m1)
1812 | | mstore(0x40, m2)
1813 | | mstore(0x60, m3)
1814 | | }
1815 | | }
1816 | |
1817 | | function log(uint256 p0, address p1, bytes32 p2) internal pure {
1818 | | bytes32 m0;
1819 | | bytes32 m1;
1820 | | bytes32 m2;
1821 | | bytes32 m3;
1822 | | bytes32 m4;
1823 | | bytes32 m5;
1824 | | /// @solidity memory-safe-assembly
1825 | | assembly {
1826 | | function writeString(pos, w) {
1827 | | let length := 0
1828 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1829 | | mstore(pos, length)
1830 | | let shift := sub(256, shl(3, length))
1831 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1832 | | }
1833 | | m0 := mload(0x00)
1834 | | m1 := mload(0x20)
1835 | | m2 := mload(0x40)
1836 | | m3 := mload(0x60)
1837 | | m4 := mload(0x80)
1838 | | m5 := mload(0xa0)
1839 | | // Selector of `log(uint256,address,string)`.
1840 | | mstore(0x00, 0x63cb41f9)
1841 | | mstore(0x20, p0)
1842 | | mstore(0x40, p1)
1843 | | mstore(0x60, 0x60)
1844 | | writeString(0x80, p2)
1845 | | }
1846 | | _sendLogPayload(0x1c, 0xa4);
1847 | | /// @solidity memory-safe-assembly
1848 | | assembly {
1849 | | mstore(0x00, m0)
1850 | | mstore(0x20, m1)
1851 | | mstore(0x40, m2)
1852 | | mstore(0x60, m3)
1853 | | mstore(0x80, m4)
1854 | | mstore(0xa0, m5)
1855 | | }
1856 | | }
1857 | |
1858 | | function log(uint256 p0, bool p1, address p2) internal pure {
1859 | | bytes32 m0;
1860 | | bytes32 m1;
1861 | | bytes32 m2;
1862 | | bytes32 m3;
1863 | | /// @solidity memory-safe-assembly
1864 | | assembly {
1865 | | m0 := mload(0x00)
1866 | | m1 := mload(0x20)
1867 | | m2 := mload(0x40)
1868 | | m3 := mload(0x60)
1869 | | // Selector of `log(uint256,bool,address)`.
1870 | | mstore(0x00, 0x35085f7b)
1871 | | mstore(0x20, p0)
1872 | | mstore(0x40, p1)
1873 | | mstore(0x60, p2)
1874 | | }
1875 | | _sendLogPayload(0x1c, 0x64);
1876 | | /// @solidity memory-safe-assembly
1877 | | assembly {
1878 | | mstore(0x00, m0)
1879 | | mstore(0x20, m1)
1880 | | mstore(0x40, m2)
1881 | | mstore(0x60, m3)
1882 | | }
1883 | | }
1884 | |
1885 | | function log(uint256 p0, bool p1, bool p2) internal pure {
1886 | | bytes32 m0;
1887 | | bytes32 m1;
1888 | | bytes32 m2;
1889 | | bytes32 m3;
1890 | | /// @solidity memory-safe-assembly
1891 | | assembly {
1892 | | m0 := mload(0x00)
1893 | | m1 := mload(0x20)
1894 | | m2 := mload(0x40)
1895 | | m3 := mload(0x60)
1896 | | // Selector of `log(uint256,bool,bool)`.
1897 | | mstore(0x00, 0x20718650)
1898 | | mstore(0x20, p0)
1899 | | mstore(0x40, p1)
1900 | | mstore(0x60, p2)
1901 | | }
1902 | | _sendLogPayload(0x1c, 0x64);
1903 | | /// @solidity memory-safe-assembly
1904 | | assembly {
1905 | | mstore(0x00, m0)
1906 | | mstore(0x20, m1)
1907 | | mstore(0x40, m2)
1908 | | mstore(0x60, m3)
1909 | | }
1910 | | }
1911 | |
1912 | | function log(uint256 p0, bool p1, uint256 p2) internal pure {
1913 | | bytes32 m0;
1914 | | bytes32 m1;
1915 | | bytes32 m2;
1916 | | bytes32 m3;
1917 | | /// @solidity memory-safe-assembly
1918 | | assembly {
1919 | | m0 := mload(0x00)
1920 | | m1 := mload(0x20)
1921 | | m2 := mload(0x40)
1922 | | m3 := mload(0x60)
1923 | | // Selector of `log(uint256,bool,uint256)`.
1924 | | mstore(0x00, 0x20098014)
1925 | | mstore(0x20, p0)
1926 | | mstore(0x40, p1)
1927 | | mstore(0x60, p2)
1928 | | }
1929 | | _sendLogPayload(0x1c, 0x64);
1930 | | /// @solidity memory-safe-assembly
1931 | | assembly {
1932 | | mstore(0x00, m0)
1933 | | mstore(0x20, m1)
1934 | | mstore(0x40, m2)
1935 | | mstore(0x60, m3)
1936 | | }
1937 | | }
1938 | |
1939 | | function log(uint256 p0, bool p1, bytes32 p2) internal pure {
1940 | | bytes32 m0;
1941 | | bytes32 m1;
1942 | | bytes32 m2;
1943 | | bytes32 m3;
1944 | | bytes32 m4;
1945 | | bytes32 m5;
1946 | | /// @solidity memory-safe-assembly
1947 | | assembly {
1948 | | function writeString(pos, w) {
1949 | | let length := 0
1950 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1951 | | mstore(pos, length)
1952 | | let shift := sub(256, shl(3, length))
1953 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1954 | | }
1955 | | m0 := mload(0x00)
1956 | | m1 := mload(0x20)
1957 | | m2 := mload(0x40)
1958 | | m3 := mload(0x60)
1959 | | m4 := mload(0x80)
1960 | | m5 := mload(0xa0)
1961 | | // Selector of `log(uint256,bool,string)`.
1962 | | mstore(0x00, 0x85775021)
1963 | | mstore(0x20, p0)
1964 | | mstore(0x40, p1)
1965 | | mstore(0x60, 0x60)
1966 | | writeString(0x80, p2)
1967 | | }
1968 | | _sendLogPayload(0x1c, 0xa4);
1969 | | /// @solidity memory-safe-assembly
1970 | | assembly {
1971 | | mstore(0x00, m0)
1972 | | mstore(0x20, m1)
1973 | | mstore(0x40, m2)
1974 | | mstore(0x60, m3)
1975 | | mstore(0x80, m4)
1976 | | mstore(0xa0, m5)
1977 | | }
1978 | | }
1979 | |
1980 | | function log(uint256 p0, uint256 p1, address p2) internal pure {
1981 | | bytes32 m0;
1982 | | bytes32 m1;
1983 | | bytes32 m2;
1984 | | bytes32 m3;
1985 | | /// @solidity memory-safe-assembly
1986 | | assembly {
1987 | | m0 := mload(0x00)
1988 | | m1 := mload(0x20)
1989 | | m2 := mload(0x40)
1990 | | m3 := mload(0x60)
1991 | | // Selector of `log(uint256,uint256,address)`.
1992 | | mstore(0x00, 0x5c96b331)
1993 | | mstore(0x20, p0)
1994 | | mstore(0x40, p1)
1995 | | mstore(0x60, p2)
1996 | | }
1997 | | _sendLogPayload(0x1c, 0x64);
1998 | | /// @solidity memory-safe-assembly
1999 | | assembly {
2000 | | mstore(0x00, m0)
2001 | | mstore(0x20, m1)
2002 | | mstore(0x40, m2)
2003 | | mstore(0x60, m3)
2004 | | }
2005 | | }
2006 | |
2007 | | function log(uint256 p0, uint256 p1, bool p2) internal pure {
2008 | | bytes32 m0;
2009 | | bytes32 m1;
2010 | | bytes32 m2;
2011 | | bytes32 m3;
2012 | | /// @solidity memory-safe-assembly
2013 | | assembly {
2014 | | m0 := mload(0x00)
2015 | | m1 := mload(0x20)
2016 | | m2 := mload(0x40)
2017 | | m3 := mload(0x60)
2018 | | // Selector of `log(uint256,uint256,bool)`.
2019 | | mstore(0x00, 0x4766da72)
2020 | | mstore(0x20, p0)
2021 | | mstore(0x40, p1)
2022 | | mstore(0x60, p2)
2023 | | }
2024 | | _sendLogPayload(0x1c, 0x64);
2025 | | /// @solidity memory-safe-assembly
2026 | | assembly {
2027 | | mstore(0x00, m0)
2028 | | mstore(0x20, m1)
2029 | | mstore(0x40, m2)
2030 | | mstore(0x60, m3)
2031 | | }
2032 | | }
2033 | |
2034 | | function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
2035 | | bytes32 m0;
2036 | | bytes32 m1;
2037 | | bytes32 m2;
2038 | | bytes32 m3;
2039 | | /// @solidity memory-safe-assembly
2040 | | assembly {
2041 | | m0 := mload(0x00)
2042 | | m1 := mload(0x20)
2043 | | m2 := mload(0x40)
2044 | | m3 := mload(0x60)
2045 | | // Selector of `log(uint256,uint256,uint256)`.
2046 | | mstore(0x00, 0xd1ed7a3c)
2047 | | mstore(0x20, p0)
2048 | | mstore(0x40, p1)
2049 | | mstore(0x60, p2)
2050 | | }
2051 | | _sendLogPayload(0x1c, 0x64);
2052 | | /// @solidity memory-safe-assembly
2053 | | assembly {
2054 | | mstore(0x00, m0)
2055 | | mstore(0x20, m1)
2056 | | mstore(0x40, m2)
2057 | | mstore(0x60, m3)
2058 | | }
2059 | | }
2060 | |
2061 | | function log(uint256 p0, uint256 p1, bytes32 p2) internal pure {
2062 | | bytes32 m0;
2063 | | bytes32 m1;
2064 | | bytes32 m2;
2065 | | bytes32 m3;
2066 | | bytes32 m4;
2067 | | bytes32 m5;
2068 | | /// @solidity memory-safe-assembly
2069 | | assembly {
2070 | | function writeString(pos, w) {
2071 | | let length := 0
2072 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2073 | | mstore(pos, length)
2074 | | let shift := sub(256, shl(3, length))
2075 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2076 | | }
2077 | | m0 := mload(0x00)
2078 | | m1 := mload(0x20)
2079 | | m2 := mload(0x40)
2080 | | m3 := mload(0x60)
2081 | | m4 := mload(0x80)
2082 | | m5 := mload(0xa0)
2083 | | // Selector of `log(uint256,uint256,string)`.
2084 | | mstore(0x00, 0x71d04af2)
2085 | | mstore(0x20, p0)
2086 | | mstore(0x40, p1)
2087 | | mstore(0x60, 0x60)
2088 | | writeString(0x80, p2)
2089 | | }
2090 | | _sendLogPayload(0x1c, 0xa4);
2091 | | /// @solidity memory-safe-assembly
2092 | | assembly {
2093 | | mstore(0x00, m0)
2094 | | mstore(0x20, m1)
2095 | | mstore(0x40, m2)
2096 | | mstore(0x60, m3)
2097 | | mstore(0x80, m4)
2098 | | mstore(0xa0, m5)
2099 | | }
2100 | | }
2101 | |
2102 | | function log(uint256 p0, bytes32 p1, address p2) internal pure {
2103 | | bytes32 m0;
2104 | | bytes32 m1;
2105 | | bytes32 m2;
2106 | | bytes32 m3;
2107 | | bytes32 m4;
2108 | | bytes32 m5;
2109 | | /// @solidity memory-safe-assembly
2110 | | assembly {
2111 | | function writeString(pos, w) {
2112 | | let length := 0
2113 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2114 | | mstore(pos, length)
2115 | | let shift := sub(256, shl(3, length))
2116 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2117 | | }
2118 | | m0 := mload(0x00)
2119 | | m1 := mload(0x20)
2120 | | m2 := mload(0x40)
2121 | | m3 := mload(0x60)
2122 | | m4 := mload(0x80)
2123 | | m5 := mload(0xa0)
2124 | | // Selector of `log(uint256,string,address)`.
2125 | | mstore(0x00, 0x7afac959)
2126 | | mstore(0x20, p0)
2127 | | mstore(0x40, 0x60)
2128 | | mstore(0x60, p2)
2129 | | writeString(0x80, p1)
2130 | | }
2131 | | _sendLogPayload(0x1c, 0xa4);
2132 | | /// @solidity memory-safe-assembly
2133 | | assembly {
2134 | | mstore(0x00, m0)
2135 | | mstore(0x20, m1)
2136 | | mstore(0x40, m2)
2137 | | mstore(0x60, m3)
2138 | | mstore(0x80, m4)
2139 | | mstore(0xa0, m5)
2140 | | }
2141 | | }
2142 | |
2143 | | function log(uint256 p0, bytes32 p1, bool p2) internal pure {
2144 | | bytes32 m0;
2145 | | bytes32 m1;
2146 | | bytes32 m2;
2147 | | bytes32 m3;
2148 | | bytes32 m4;
2149 | | bytes32 m5;
2150 | | /// @solidity memory-safe-assembly
2151 | | assembly {
2152 | | function writeString(pos, w) {
2153 | | let length := 0
2154 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2155 | | mstore(pos, length)
2156 | | let shift := sub(256, shl(3, length))
2157 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2158 | | }
2159 | | m0 := mload(0x00)
2160 | | m1 := mload(0x20)
2161 | | m2 := mload(0x40)
2162 | | m3 := mload(0x60)
2163 | | m4 := mload(0x80)
2164 | | m5 := mload(0xa0)
2165 | | // Selector of `log(uint256,string,bool)`.
2166 | | mstore(0x00, 0x4ceda75a)
2167 | | mstore(0x20, p0)
2168 | | mstore(0x40, 0x60)
2169 | | mstore(0x60, p2)
2170 | | writeString(0x80, p1)
2171 | | }
2172 | | _sendLogPayload(0x1c, 0xa4);
2173 | | /// @solidity memory-safe-assembly
2174 | | assembly {
2175 | | mstore(0x00, m0)
2176 | | mstore(0x20, m1)
2177 | | mstore(0x40, m2)
2178 | | mstore(0x60, m3)
2179 | | mstore(0x80, m4)
2180 | | mstore(0xa0, m5)
2181 | | }
2182 | | }
2183 | |
2184 | | function log(uint256 p0, bytes32 p1, uint256 p2) internal pure {
2185 | | bytes32 m0;
2186 | | bytes32 m1;
2187 | | bytes32 m2;
2188 | | bytes32 m3;
2189 | | bytes32 m4;
2190 | | bytes32 m5;
2191 | | /// @solidity memory-safe-assembly
2192 | | assembly {
2193 | | function writeString(pos, w) {
2194 | | let length := 0
2195 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2196 | | mstore(pos, length)
2197 | | let shift := sub(256, shl(3, length))
2198 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2199 | | }
2200 | | m0 := mload(0x00)
2201 | | m1 := mload(0x20)
2202 | | m2 := mload(0x40)
2203 | | m3 := mload(0x60)
2204 | | m4 := mload(0x80)
2205 | | m5 := mload(0xa0)
2206 | | // Selector of `log(uint256,string,uint256)`.
2207 | | mstore(0x00, 0x37aa7d4c)
2208 | | mstore(0x20, p0)
2209 | | mstore(0x40, 0x60)
2210 | | mstore(0x60, p2)
2211 | | writeString(0x80, p1)
2212 | | }
2213 | | _sendLogPayload(0x1c, 0xa4);
2214 | | /// @solidity memory-safe-assembly
2215 | | assembly {
2216 | | mstore(0x00, m0)
2217 | | mstore(0x20, m1)
2218 | | mstore(0x40, m2)
2219 | | mstore(0x60, m3)
2220 | | mstore(0x80, m4)
2221 | | mstore(0xa0, m5)
2222 | | }
2223 | | }
2224 | |
2225 | | function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure {
2226 | | bytes32 m0;
2227 | | bytes32 m1;
2228 | | bytes32 m2;
2229 | | bytes32 m3;
2230 | | bytes32 m4;
2231 | | bytes32 m5;
2232 | | bytes32 m6;
2233 | | bytes32 m7;
2234 | | /// @solidity memory-safe-assembly
2235 | | assembly {
2236 | | function writeString(pos, w) {
2237 | | let length := 0
2238 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2239 | | mstore(pos, length)
2240 | | let shift := sub(256, shl(3, length))
2241 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2242 | | }
2243 | | m0 := mload(0x00)
2244 | | m1 := mload(0x20)
2245 | | m2 := mload(0x40)
2246 | | m3 := mload(0x60)
2247 | | m4 := mload(0x80)
2248 | | m5 := mload(0xa0)
2249 | | m6 := mload(0xc0)
2250 | | m7 := mload(0xe0)
2251 | | // Selector of `log(uint256,string,string)`.
2252 | | mstore(0x00, 0xb115611f)
2253 | | mstore(0x20, p0)
2254 | | mstore(0x40, 0x60)
2255 | | mstore(0x60, 0xa0)
2256 | | writeString(0x80, p1)
2257 | | writeString(0xc0, p2)
2258 | | }
2259 | | _sendLogPayload(0x1c, 0xe4);
2260 | | /// @solidity memory-safe-assembly
2261 | | assembly {
2262 | | mstore(0x00, m0)
2263 | | mstore(0x20, m1)
2264 | | mstore(0x40, m2)
2265 | | mstore(0x60, m3)
2266 | | mstore(0x80, m4)
2267 | | mstore(0xa0, m5)
2268 | | mstore(0xc0, m6)
2269 | | mstore(0xe0, m7)
2270 | | }
2271 | | }
2272 | |
2273 | | function log(bytes32 p0, address p1, address p2) internal pure {
2274 | | bytes32 m0;
2275 | | bytes32 m1;
2276 | | bytes32 m2;
2277 | | bytes32 m3;
2278 | | bytes32 m4;
2279 | | bytes32 m5;
2280 | | /// @solidity memory-safe-assembly
2281 | | assembly {
2282 | | function writeString(pos, w) {
2283 | | let length := 0
2284 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2285 | | mstore(pos, length)
2286 | | let shift := sub(256, shl(3, length))
2287 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2288 | | }
2289 | | m0 := mload(0x00)
2290 | | m1 := mload(0x20)
2291 | | m2 := mload(0x40)
2292 | | m3 := mload(0x60)
2293 | | m4 := mload(0x80)
2294 | | m5 := mload(0xa0)
2295 | | // Selector of `log(string,address,address)`.
2296 | | mstore(0x00, 0xfcec75e0)
2297 | | mstore(0x20, 0x60)
2298 | | mstore(0x40, p1)
2299 | | mstore(0x60, p2)
2300 | | writeString(0x80, p0)
2301 | | }
2302 | | _sendLogPayload(0x1c, 0xa4);
2303 | | /// @solidity memory-safe-assembly
2304 | | assembly {
2305 | | mstore(0x00, m0)
2306 | | mstore(0x20, m1)
2307 | | mstore(0x40, m2)
2308 | | mstore(0x60, m3)
2309 | | mstore(0x80, m4)
2310 | | mstore(0xa0, m5)
2311 | | }
2312 | | }
2313 | |
2314 | | function log(bytes32 p0, address p1, bool p2) internal pure {
2315 | | bytes32 m0;
2316 | | bytes32 m1;
2317 | | bytes32 m2;
2318 | | bytes32 m3;
2319 | | bytes32 m4;
2320 | | bytes32 m5;
2321 | | /// @solidity memory-safe-assembly
2322 | | assembly {
2323 | | function writeString(pos, w) {
2324 | | let length := 0
2325 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2326 | | mstore(pos, length)
2327 | | let shift := sub(256, shl(3, length))
2328 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2329 | | }
2330 | | m0 := mload(0x00)
2331 | | m1 := mload(0x20)
2332 | | m2 := mload(0x40)
2333 | | m3 := mload(0x60)
2334 | | m4 := mload(0x80)
2335 | | m5 := mload(0xa0)
2336 | | // Selector of `log(string,address,bool)`.
2337 | | mstore(0x00, 0xc91d5ed4)
2338 | | mstore(0x20, 0x60)
2339 | | mstore(0x40, p1)
2340 | | mstore(0x60, p2)
2341 | | writeString(0x80, p0)
2342 | | }
2343 | | _sendLogPayload(0x1c, 0xa4);
2344 | | /// @solidity memory-safe-assembly
2345 | | assembly {
2346 | | mstore(0x00, m0)
2347 | | mstore(0x20, m1)
2348 | | mstore(0x40, m2)
2349 | | mstore(0x60, m3)
2350 | | mstore(0x80, m4)
2351 | | mstore(0xa0, m5)
2352 | | }
2353 | | }
2354 | |
2355 | | function log(bytes32 p0, address p1, uint256 p2) internal pure {
2356 | | bytes32 m0;
2357 | | bytes32 m1;
2358 | | bytes32 m2;
2359 | | bytes32 m3;
2360 | | bytes32 m4;
2361 | | bytes32 m5;
2362 | | /// @solidity memory-safe-assembly
2363 | | assembly {
2364 | | function writeString(pos, w) {
2365 | | let length := 0
2366 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2367 | | mstore(pos, length)
2368 | | let shift := sub(256, shl(3, length))
2369 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2370 | | }
2371 | | m0 := mload(0x00)
2372 | | m1 := mload(0x20)
2373 | | m2 := mload(0x40)
2374 | | m3 := mload(0x60)
2375 | | m4 := mload(0x80)
2376 | | m5 := mload(0xa0)
2377 | | // Selector of `log(string,address,uint256)`.
2378 | | mstore(0x00, 0x0d26b925)
2379 | | mstore(0x20, 0x60)
2380 | | mstore(0x40, p1)
2381 | | mstore(0x60, p2)
2382 | | writeString(0x80, p0)
2383 | | }
2384 | | _sendLogPayload(0x1c, 0xa4);
2385 | | /// @solidity memory-safe-assembly
2386 | | assembly {
2387 | | mstore(0x00, m0)
2388 | | mstore(0x20, m1)
2389 | | mstore(0x40, m2)
2390 | | mstore(0x60, m3)
2391 | | mstore(0x80, m4)
2392 | | mstore(0xa0, m5)
2393 | | }
2394 | | }
2395 | |
2396 | | function log(bytes32 p0, address p1, bytes32 p2) internal pure {
2397 | | bytes32 m0;
2398 | | bytes32 m1;
2399 | | bytes32 m2;
2400 | | bytes32 m3;
2401 | | bytes32 m4;
2402 | | bytes32 m5;
2403 | | bytes32 m6;
2404 | | bytes32 m7;
2405 | | /// @solidity memory-safe-assembly
2406 | | assembly {
2407 | | function writeString(pos, w) {
2408 | | let length := 0
2409 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2410 | | mstore(pos, length)
2411 | | let shift := sub(256, shl(3, length))
2412 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2413 | | }
2414 | | m0 := mload(0x00)
2415 | | m1 := mload(0x20)
2416 | | m2 := mload(0x40)
2417 | | m3 := mload(0x60)
2418 | | m4 := mload(0x80)
2419 | | m5 := mload(0xa0)
2420 | | m6 := mload(0xc0)
2421 | | m7 := mload(0xe0)
2422 | | // Selector of `log(string,address,string)`.
2423 | | mstore(0x00, 0xe0e9ad4f)
2424 | | mstore(0x20, 0x60)
2425 | | mstore(0x40, p1)
2426 | | mstore(0x60, 0xa0)
2427 | | writeString(0x80, p0)
2428 | | writeString(0xc0, p2)
2429 | | }
2430 | | _sendLogPayload(0x1c, 0xe4);
2431 | | /// @solidity memory-safe-assembly
2432 | | assembly {
2433 | | mstore(0x00, m0)
2434 | | mstore(0x20, m1)
2435 | | mstore(0x40, m2)
2436 | | mstore(0x60, m3)
2437 | | mstore(0x80, m4)
2438 | | mstore(0xa0, m5)
2439 | | mstore(0xc0, m6)
2440 | | mstore(0xe0, m7)
2441 | | }
2442 | | }
2443 | |
2444 | | function log(bytes32 p0, bool p1, address p2) internal pure {
2445 | | bytes32 m0;
2446 | | bytes32 m1;
2447 | | bytes32 m2;
2448 | | bytes32 m3;
2449 | | bytes32 m4;
2450 | | bytes32 m5;
2451 | | /// @solidity memory-safe-assembly
2452 | | assembly {
2453 | | function writeString(pos, w) {
2454 | | let length := 0
2455 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2456 | | mstore(pos, length)
2457 | | let shift := sub(256, shl(3, length))
2458 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2459 | | }
2460 | | m0 := mload(0x00)
2461 | | m1 := mload(0x20)
2462 | | m2 := mload(0x40)
2463 | | m3 := mload(0x60)
2464 | | m4 := mload(0x80)
2465 | | m5 := mload(0xa0)
2466 | | // Selector of `log(string,bool,address)`.
2467 | | mstore(0x00, 0x932bbb38)
2468 | | mstore(0x20, 0x60)
2469 | | mstore(0x40, p1)
2470 | | mstore(0x60, p2)
2471 | | writeString(0x80, p0)
2472 | | }
2473 | | _sendLogPayload(0x1c, 0xa4);
2474 | | /// @solidity memory-safe-assembly
2475 | | assembly {
2476 | | mstore(0x00, m0)
2477 | | mstore(0x20, m1)
2478 | | mstore(0x40, m2)
2479 | | mstore(0x60, m3)
2480 | | mstore(0x80, m4)
2481 | | mstore(0xa0, m5)
2482 | | }
2483 | | }
2484 | |
2485 | | function log(bytes32 p0, bool p1, bool p2) internal pure {
2486 | | bytes32 m0;
2487 | | bytes32 m1;
2488 | | bytes32 m2;
2489 | | bytes32 m3;
2490 | | bytes32 m4;
2491 | | bytes32 m5;
2492 | | /// @solidity memory-safe-assembly
2493 | | assembly {
2494 | | function writeString(pos, w) {
2495 | | let length := 0
2496 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2497 | | mstore(pos, length)
2498 | | let shift := sub(256, shl(3, length))
2499 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2500 | | }
2501 | | m0 := mload(0x00)
2502 | | m1 := mload(0x20)
2503 | | m2 := mload(0x40)
2504 | | m3 := mload(0x60)
2505 | | m4 := mload(0x80)
2506 | | m5 := mload(0xa0)
2507 | | // Selector of `log(string,bool,bool)`.
2508 | | mstore(0x00, 0x850b7ad6)
2509 | | mstore(0x20, 0x60)
2510 | | mstore(0x40, p1)
2511 | | mstore(0x60, p2)
2512 | | writeString(0x80, p0)
2513 | | }
2514 | | _sendLogPayload(0x1c, 0xa4);
2515 | | /// @solidity memory-safe-assembly
2516 | | assembly {
2517 | | mstore(0x00, m0)
2518 | | mstore(0x20, m1)
2519 | | mstore(0x40, m2)
2520 | | mstore(0x60, m3)
2521 | | mstore(0x80, m4)
2522 | | mstore(0xa0, m5)
2523 | | }
2524 | | }
2525 | |
2526 | | function log(bytes32 p0, bool p1, uint256 p2) internal pure {
2527 | | bytes32 m0;
2528 | | bytes32 m1;
2529 | | bytes32 m2;
2530 | | bytes32 m3;
2531 | | bytes32 m4;
2532 | | bytes32 m5;
2533 | | /// @solidity memory-safe-assembly
2534 | | assembly {
2535 | | function writeString(pos, w) {
2536 | | let length := 0
2537 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2538 | | mstore(pos, length)
2539 | | let shift := sub(256, shl(3, length))
2540 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2541 | | }
2542 | | m0 := mload(0x00)
2543 | | m1 := mload(0x20)
2544 | | m2 := mload(0x40)
2545 | | m3 := mload(0x60)
2546 | | m4 := mload(0x80)
2547 | | m5 := mload(0xa0)
2548 | | // Selector of `log(string,bool,uint256)`.
2549 | | mstore(0x00, 0xc95958d6)
2550 | | mstore(0x20, 0x60)
2551 | | mstore(0x40, p1)
2552 | | mstore(0x60, p2)
2553 | | writeString(0x80, p0)
2554 | | }
2555 | | _sendLogPayload(0x1c, 0xa4);
2556 | | /// @solidity memory-safe-assembly
2557 | | assembly {
2558 | | mstore(0x00, m0)
2559 | | mstore(0x20, m1)
2560 | | mstore(0x40, m2)
2561 | | mstore(0x60, m3)
2562 | | mstore(0x80, m4)
2563 | | mstore(0xa0, m5)
2564 | | }
2565 | | }
2566 | |
2567 | | function log(bytes32 p0, bool p1, bytes32 p2) internal pure {
2568 | | bytes32 m0;
2569 | | bytes32 m1;
2570 | | bytes32 m2;
2571 | | bytes32 m3;
2572 | | bytes32 m4;
2573 | | bytes32 m5;
2574 | | bytes32 m6;
2575 | | bytes32 m7;
2576 | | /// @solidity memory-safe-assembly
2577 | | assembly {
2578 | | function writeString(pos, w) {
2579 | | let length := 0
2580 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2581 | | mstore(pos, length)
2582 | | let shift := sub(256, shl(3, length))
2583 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2584 | | }
2585 | | m0 := mload(0x00)
2586 | | m1 := mload(0x20)
2587 | | m2 := mload(0x40)
2588 | | m3 := mload(0x60)
2589 | | m4 := mload(0x80)
2590 | | m5 := mload(0xa0)
2591 | | m6 := mload(0xc0)
2592 | | m7 := mload(0xe0)
2593 | | // Selector of `log(string,bool,string)`.
2594 | | mstore(0x00, 0xe298f47d)
2595 | | mstore(0x20, 0x60)
2596 | | mstore(0x40, p1)
2597 | | mstore(0x60, 0xa0)
2598 | | writeString(0x80, p0)
2599 | | writeString(0xc0, p2)
2600 | | }
2601 | | _sendLogPayload(0x1c, 0xe4);
2602 | | /// @solidity memory-safe-assembly
2603 | | assembly {
2604 | | mstore(0x00, m0)
2605 | | mstore(0x20, m1)
2606 | | mstore(0x40, m2)
2607 | | mstore(0x60, m3)
2608 | | mstore(0x80, m4)
2609 | | mstore(0xa0, m5)
2610 | | mstore(0xc0, m6)
2611 | | mstore(0xe0, m7)
2612 | | }
2613 | | }
2614 | |
2615 | | function log(bytes32 p0, uint256 p1, address p2) internal pure {
2616 | | bytes32 m0;
2617 | | bytes32 m1;
2618 | | bytes32 m2;
2619 | | bytes32 m3;
2620 | | bytes32 m4;
2621 | | bytes32 m5;
2622 | | /// @solidity memory-safe-assembly
2623 | | assembly {
2624 | | function writeString(pos, w) {
2625 | | let length := 0
2626 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2627 | | mstore(pos, length)
2628 | | let shift := sub(256, shl(3, length))
2629 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2630 | | }
2631 | | m0 := mload(0x00)
2632 | | m1 := mload(0x20)
2633 | | m2 := mload(0x40)
2634 | | m3 := mload(0x60)
2635 | | m4 := mload(0x80)
2636 | | m5 := mload(0xa0)
2637 | | // Selector of `log(string,uint256,address)`.
2638 | | mstore(0x00, 0x1c7ec448)
2639 | | mstore(0x20, 0x60)
2640 | | mstore(0x40, p1)
2641 | | mstore(0x60, p2)
2642 | | writeString(0x80, p0)
2643 | | }
2644 | | _sendLogPayload(0x1c, 0xa4);
2645 | | /// @solidity memory-safe-assembly
2646 | | assembly {
2647 | | mstore(0x00, m0)
2648 | | mstore(0x20, m1)
2649 | | mstore(0x40, m2)
2650 | | mstore(0x60, m3)
2651 | | mstore(0x80, m4)
2652 | | mstore(0xa0, m5)
2653 | | }
2654 | | }
2655 | |
2656 | | function log(bytes32 p0, uint256 p1, bool p2) internal pure {
2657 | | bytes32 m0;
2658 | | bytes32 m1;
2659 | | bytes32 m2;
2660 | | bytes32 m3;
2661 | | bytes32 m4;
2662 | | bytes32 m5;
2663 | | /// @solidity memory-safe-assembly
2664 | | assembly {
2665 | | function writeString(pos, w) {
2666 | | let length := 0
2667 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2668 | | mstore(pos, length)
2669 | | let shift := sub(256, shl(3, length))
2670 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2671 | | }
2672 | | m0 := mload(0x00)
2673 | | m1 := mload(0x20)
2674 | | m2 := mload(0x40)
2675 | | m3 := mload(0x60)
2676 | | m4 := mload(0x80)
2677 | | m5 := mload(0xa0)
2678 | | // Selector of `log(string,uint256,bool)`.
2679 | | mstore(0x00, 0xca7733b1)
2680 | | mstore(0x20, 0x60)
2681 | | mstore(0x40, p1)
2682 | | mstore(0x60, p2)
2683 | | writeString(0x80, p0)
2684 | | }
2685 | | _sendLogPayload(0x1c, 0xa4);
2686 | | /// @solidity memory-safe-assembly
2687 | | assembly {
2688 | | mstore(0x00, m0)
2689 | | mstore(0x20, m1)
2690 | | mstore(0x40, m2)
2691 | | mstore(0x60, m3)
2692 | | mstore(0x80, m4)
2693 | | mstore(0xa0, m5)
2694 | | }
2695 | | }
2696 | |
2697 | | function log(bytes32 p0, uint256 p1, uint256 p2) internal pure {
2698 | | bytes32 m0;
2699 | | bytes32 m1;
2700 | | bytes32 m2;
2701 | | bytes32 m3;
2702 | | bytes32 m4;
2703 | | bytes32 m5;
2704 | | /// @solidity memory-safe-assembly
2705 | | assembly {
2706 | | function writeString(pos, w) {
2707 | | let length := 0
2708 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2709 | | mstore(pos, length)
2710 | | let shift := sub(256, shl(3, length))
2711 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2712 | | }
2713 | | m0 := mload(0x00)
2714 | | m1 := mload(0x20)
2715 | | m2 := mload(0x40)
2716 | | m3 := mload(0x60)
2717 | | m4 := mload(0x80)
2718 | | m5 := mload(0xa0)
2719 | | // Selector of `log(string,uint256,uint256)`.
2720 | | mstore(0x00, 0xca47c4eb)
2721 | | mstore(0x20, 0x60)
2722 | | mstore(0x40, p1)
2723 | | mstore(0x60, p2)
2724 | | writeString(0x80, p0)
2725 | | }
2726 | | _sendLogPayload(0x1c, 0xa4);
2727 | | /// @solidity memory-safe-assembly
2728 | | assembly {
2729 | | mstore(0x00, m0)
2730 | | mstore(0x20, m1)
2731 | | mstore(0x40, m2)
2732 | | mstore(0x60, m3)
2733 | | mstore(0x80, m4)
2734 | | mstore(0xa0, m5)
2735 | | }
2736 | | }
2737 | |
2738 | | function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure {
2739 | | bytes32 m0;
2740 | | bytes32 m1;
2741 | | bytes32 m2;
2742 | | bytes32 m3;
2743 | | bytes32 m4;
2744 | | bytes32 m5;
2745 | | bytes32 m6;
2746 | | bytes32 m7;
2747 | | /// @solidity memory-safe-assembly
2748 | | assembly {
2749 | | function writeString(pos, w) {
2750 | | let length := 0
2751 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2752 | | mstore(pos, length)
2753 | | let shift := sub(256, shl(3, length))
2754 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2755 | | }
2756 | | m0 := mload(0x00)
2757 | | m1 := mload(0x20)
2758 | | m2 := mload(0x40)
2759 | | m3 := mload(0x60)
2760 | | m4 := mload(0x80)
2761 | | m5 := mload(0xa0)
2762 | | m6 := mload(0xc0)
2763 | | m7 := mload(0xe0)
2764 | | // Selector of `log(string,uint256,string)`.
2765 | | mstore(0x00, 0x5970e089)
2766 | | mstore(0x20, 0x60)
2767 | | mstore(0x40, p1)
2768 | | mstore(0x60, 0xa0)
2769 | | writeString(0x80, p0)
2770 | | writeString(0xc0, p2)
2771 | | }
2772 | | _sendLogPayload(0x1c, 0xe4);
2773 | | /// @solidity memory-safe-assembly
2774 | | assembly {
2775 | | mstore(0x00, m0)
2776 | | mstore(0x20, m1)
2777 | | mstore(0x40, m2)
2778 | | mstore(0x60, m3)
2779 | | mstore(0x80, m4)
2780 | | mstore(0xa0, m5)
2781 | | mstore(0xc0, m6)
2782 | | mstore(0xe0, m7)
2783 | | }
2784 | | }
2785 | |
2786 | | function log(bytes32 p0, bytes32 p1, address p2) internal pure {
2787 | | bytes32 m0;
2788 | | bytes32 m1;
2789 | | bytes32 m2;
2790 | | bytes32 m3;
2791 | | bytes32 m4;
2792 | | bytes32 m5;
2793 | | bytes32 m6;
2794 | | bytes32 m7;
2795 | | /// @solidity memory-safe-assembly
2796 | | assembly {
2797 | | function writeString(pos, w) {
2798 | | let length := 0
2799 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2800 | | mstore(pos, length)
2801 | | let shift := sub(256, shl(3, length))
2802 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2803 | | }
2804 | | m0 := mload(0x00)
2805 | | m1 := mload(0x20)
2806 | | m2 := mload(0x40)
2807 | | m3 := mload(0x60)
2808 | | m4 := mload(0x80)
2809 | | m5 := mload(0xa0)
2810 | | m6 := mload(0xc0)
2811 | | m7 := mload(0xe0)
2812 | | // Selector of `log(string,string,address)`.
2813 | | mstore(0x00, 0x95ed0195)
2814 | | mstore(0x20, 0x60)
2815 | | mstore(0x40, 0xa0)
2816 | | mstore(0x60, p2)
2817 | | writeString(0x80, p0)
2818 | | writeString(0xc0, p1)
2819 | | }
2820 | | _sendLogPayload(0x1c, 0xe4);
2821 | | /// @solidity memory-safe-assembly
2822 | | assembly {
2823 | | mstore(0x00, m0)
2824 | | mstore(0x20, m1)
2825 | | mstore(0x40, m2)
2826 | | mstore(0x60, m3)
2827 | | mstore(0x80, m4)
2828 | | mstore(0xa0, m5)
2829 | | mstore(0xc0, m6)
2830 | | mstore(0xe0, m7)
2831 | | }
2832 | | }
2833 | |
2834 | | function log(bytes32 p0, bytes32 p1, bool p2) internal pure {
2835 | | bytes32 m0;
2836 | | bytes32 m1;
2837 | | bytes32 m2;
2838 | | bytes32 m3;
2839 | | bytes32 m4;
2840 | | bytes32 m5;
2841 | | bytes32 m6;
2842 | | bytes32 m7;
2843 | | /// @solidity memory-safe-assembly
2844 | | assembly {
2845 | | function writeString(pos, w) {
2846 | | let length := 0
2847 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2848 | | mstore(pos, length)
2849 | | let shift := sub(256, shl(3, length))
2850 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2851 | | }
2852 | | m0 := mload(0x00)
2853 | | m1 := mload(0x20)
2854 | | m2 := mload(0x40)
2855 | | m3 := mload(0x60)
2856 | | m4 := mload(0x80)
2857 | | m5 := mload(0xa0)
2858 | | m6 := mload(0xc0)
2859 | | m7 := mload(0xe0)
2860 | | // Selector of `log(string,string,bool)`.
2861 | | mstore(0x00, 0xb0e0f9b5)
2862 | | mstore(0x20, 0x60)
2863 | | mstore(0x40, 0xa0)
2864 | | mstore(0x60, p2)
2865 | | writeString(0x80, p0)
2866 | | writeString(0xc0, p1)
2867 | | }
2868 | | _sendLogPayload(0x1c, 0xe4);
2869 | | /// @solidity memory-safe-assembly
2870 | | assembly {
2871 | | mstore(0x00, m0)
2872 | | mstore(0x20, m1)
2873 | | mstore(0x40, m2)
2874 | | mstore(0x60, m3)
2875 | | mstore(0x80, m4)
2876 | | mstore(0xa0, m5)
2877 | | mstore(0xc0, m6)
2878 | | mstore(0xe0, m7)
2879 | | }
2880 | | }
2881 | |
2882 | | function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure {
2883 | | bytes32 m0;
2884 | | bytes32 m1;
2885 | | bytes32 m2;
2886 | | bytes32 m3;
2887 | | bytes32 m4;
2888 | | bytes32 m5;
2889 | | bytes32 m6;
2890 | | bytes32 m7;
2891 | | /// @solidity memory-safe-assembly
2892 | | assembly {
2893 | | function writeString(pos, w) {
2894 | | let length := 0
2895 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2896 | | mstore(pos, length)
2897 | | let shift := sub(256, shl(3, length))
2898 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2899 | | }
2900 | | m0 := mload(0x00)
2901 | | m1 := mload(0x20)
2902 | | m2 := mload(0x40)
2903 | | m3 := mload(0x60)
2904 | | m4 := mload(0x80)
2905 | | m5 := mload(0xa0)
2906 | | m6 := mload(0xc0)
2907 | | m7 := mload(0xe0)
2908 | | // Selector of `log(string,string,uint256)`.
2909 | | mstore(0x00, 0x5821efa1)
2910 | | mstore(0x20, 0x60)
2911 | | mstore(0x40, 0xa0)
2912 | | mstore(0x60, p2)
2913 | | writeString(0x80, p0)
2914 | | writeString(0xc0, p1)
2915 | | }
2916 | | _sendLogPayload(0x1c, 0xe4);
2917 | | /// @solidity memory-safe-assembly
2918 | | assembly {
2919 | | mstore(0x00, m0)
2920 | | mstore(0x20, m1)
2921 | | mstore(0x40, m2)
2922 | | mstore(0x60, m3)
2923 | | mstore(0x80, m4)
2924 | | mstore(0xa0, m5)
2925 | | mstore(0xc0, m6)
2926 | | mstore(0xe0, m7)
2927 | | }
2928 | | }
2929 | |
2930 | | function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure {
2931 | | bytes32 m0;
2932 | | bytes32 m1;
2933 | | bytes32 m2;
2934 | | bytes32 m3;
2935 | | bytes32 m4;
2936 | | bytes32 m5;
2937 | | bytes32 m6;
2938 | | bytes32 m7;
2939 | | bytes32 m8;
2940 | | bytes32 m9;
2941 | | /// @solidity memory-safe-assembly
2942 | | assembly {
2943 | | function writeString(pos, w) {
2944 | | let length := 0
2945 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2946 | | mstore(pos, length)
2947 | | let shift := sub(256, shl(3, length))
2948 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2949 | | }
2950 | | m0 := mload(0x00)
2951 | | m1 := mload(0x20)
2952 | | m2 := mload(0x40)
2953 | | m3 := mload(0x60)
2954 | | m4 := mload(0x80)
2955 | | m5 := mload(0xa0)
2956 | | m6 := mload(0xc0)
2957 | | m7 := mload(0xe0)
2958 | | m8 := mload(0x100)
2959 | | m9 := mload(0x120)
2960 | | // Selector of `log(string,string,string)`.
2961 | | mstore(0x00, 0x2ced7cef)
2962 | | mstore(0x20, 0x60)
2963 | | mstore(0x40, 0xa0)
2964 | | mstore(0x60, 0xe0)
2965 | | writeString(0x80, p0)
2966 | | writeString(0xc0, p1)
2967 | | writeString(0x100, p2)
2968 | | }
2969 | | _sendLogPayload(0x1c, 0x124);
2970 | | /// @solidity memory-safe-assembly
2971 | | assembly {
2972 | | mstore(0x00, m0)
2973 | | mstore(0x20, m1)
2974 | | mstore(0x40, m2)
2975 | | mstore(0x60, m3)
2976 | | mstore(0x80, m4)
2977 | | mstore(0xa0, m5)
2978 | | mstore(0xc0, m6)
2979 | | mstore(0xe0, m7)
2980 | | mstore(0x100, m8)
2981 | | mstore(0x120, m9)
2982 | | }
2983 | | }
2984 | |
2985 | | function log(address p0, address p1, address p2, address p3) internal pure {
2986 | | bytes32 m0;
2987 | | bytes32 m1;
2988 | | bytes32 m2;
2989 | | bytes32 m3;
2990 | | bytes32 m4;
2991 | | /// @solidity memory-safe-assembly
2992 | | assembly {
2993 | | m0 := mload(0x00)
2994 | | m1 := mload(0x20)
2995 | | m2 := mload(0x40)
2996 | | m3 := mload(0x60)
2997 | | m4 := mload(0x80)
2998 | | // Selector of `log(address,address,address,address)`.
2999 | | mstore(0x00, 0x665bf134)
3000 | | mstore(0x20, p0)
3001 | | mstore(0x40, p1)
3002 | | mstore(0x60, p2)
3003 | | mstore(0x80, p3)
3004 | | }
3005 | | _sendLogPayload(0x1c, 0x84);
3006 | | /// @solidity memory-safe-assembly
3007 | | assembly {
3008 | | mstore(0x00, m0)
3009 | | mstore(0x20, m1)
3010 | | mstore(0x40, m2)
3011 | | mstore(0x60, m3)
3012 | | mstore(0x80, m4)
3013 | | }
3014 | | }
3015 | |
3016 | | function log(address p0, address p1, address p2, bool p3) internal pure {
3017 | | bytes32 m0;
3018 | | bytes32 m1;
3019 | | bytes32 m2;
3020 | | bytes32 m3;
3021 | | bytes32 m4;
3022 | | /// @solidity memory-safe-assembly
3023 | | assembly {
3024 | | m0 := mload(0x00)
3025 | | m1 := mload(0x20)
3026 | | m2 := mload(0x40)
3027 | | m3 := mload(0x60)
3028 | | m4 := mload(0x80)
3029 | | // Selector of `log(address,address,address,bool)`.
3030 | | mstore(0x00, 0x0e378994)
3031 | | mstore(0x20, p0)
3032 | | mstore(0x40, p1)
3033 | | mstore(0x60, p2)
3034 | | mstore(0x80, p3)
3035 | | }
3036 | | _sendLogPayload(0x1c, 0x84);
3037 | | /// @solidity memory-safe-assembly
3038 | | assembly {
3039 | | mstore(0x00, m0)
3040 | | mstore(0x20, m1)
3041 | | mstore(0x40, m2)
3042 | | mstore(0x60, m3)
3043 | | mstore(0x80, m4)
3044 | | }
3045 | | }
3046 | |
3047 | | function log(address p0, address p1, address p2, uint256 p3) internal pure {
3048 | | bytes32 m0;
3049 | | bytes32 m1;
3050 | | bytes32 m2;
3051 | | bytes32 m3;
3052 | | bytes32 m4;
3053 | | /// @solidity memory-safe-assembly
3054 | | assembly {
3055 | | m0 := mload(0x00)
3056 | | m1 := mload(0x20)
3057 | | m2 := mload(0x40)
3058 | | m3 := mload(0x60)
3059 | | m4 := mload(0x80)
3060 | | // Selector of `log(address,address,address,uint256)`.
3061 | | mstore(0x00, 0x94250d77)
3062 | | mstore(0x20, p0)
3063 | | mstore(0x40, p1)
3064 | | mstore(0x60, p2)
3065 | | mstore(0x80, p3)
3066 | | }
3067 | | _sendLogPayload(0x1c, 0x84);
3068 | | /// @solidity memory-safe-assembly
3069 | | assembly {
3070 | | mstore(0x00, m0)
3071 | | mstore(0x20, m1)
3072 | | mstore(0x40, m2)
3073 | | mstore(0x60, m3)
3074 | | mstore(0x80, m4)
3075 | | }
3076 | | }
3077 | |
3078 | | function log(address p0, address p1, address p2, bytes32 p3) internal pure {
3079 | | bytes32 m0;
3080 | | bytes32 m1;
3081 | | bytes32 m2;
3082 | | bytes32 m3;
3083 | | bytes32 m4;
3084 | | bytes32 m5;
3085 | | bytes32 m6;
3086 | | /// @solidity memory-safe-assembly
3087 | | assembly {
3088 | | function writeString(pos, w) {
3089 | | let length := 0
3090 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3091 | | mstore(pos, length)
3092 | | let shift := sub(256, shl(3, length))
3093 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3094 | | }
3095 | | m0 := mload(0x00)
3096 | | m1 := mload(0x20)
3097 | | m2 := mload(0x40)
3098 | | m3 := mload(0x60)
3099 | | m4 := mload(0x80)
3100 | | m5 := mload(0xa0)
3101 | | m6 := mload(0xc0)
3102 | | // Selector of `log(address,address,address,string)`.
3103 | | mstore(0x00, 0xf808da20)
3104 | | mstore(0x20, p0)
3105 | | mstore(0x40, p1)
3106 | | mstore(0x60, p2)
3107 | | mstore(0x80, 0x80)
3108 | | writeString(0xa0, p3)
3109 | | }
3110 | | _sendLogPayload(0x1c, 0xc4);
3111 | | /// @solidity memory-safe-assembly
3112 | | assembly {
3113 | | mstore(0x00, m0)
3114 | | mstore(0x20, m1)
3115 | | mstore(0x40, m2)
3116 | | mstore(0x60, m3)
3117 | | mstore(0x80, m4)
3118 | | mstore(0xa0, m5)
3119 | | mstore(0xc0, m6)
3120 | | }
3121 | | }
3122 | |
3123 | | function log(address p0, address p1, bool p2, address p3) internal pure {
3124 | | bytes32 m0;
3125 | | bytes32 m1;
3126 | | bytes32 m2;
3127 | | bytes32 m3;
3128 | | bytes32 m4;
3129 | | /// @solidity memory-safe-assembly
3130 | | assembly {
3131 | | m0 := mload(0x00)
3132 | | m1 := mload(0x20)
3133 | | m2 := mload(0x40)
3134 | | m3 := mload(0x60)
3135 | | m4 := mload(0x80)
3136 | | // Selector of `log(address,address,bool,address)`.
3137 | | mstore(0x00, 0x9f1bc36e)
3138 | | mstore(0x20, p0)
3139 | | mstore(0x40, p1)
3140 | | mstore(0x60, p2)
3141 | | mstore(0x80, p3)
3142 | | }
3143 | | _sendLogPayload(0x1c, 0x84);
3144 | | /// @solidity memory-safe-assembly
3145 | | assembly {
3146 | | mstore(0x00, m0)
3147 | | mstore(0x20, m1)
3148 | | mstore(0x40, m2)
3149 | | mstore(0x60, m3)
3150 | | mstore(0x80, m4)
3151 | | }
3152 | | }
3153 | |
3154 | | function log(address p0, address p1, bool p2, bool p3) internal pure {
3155 | | bytes32 m0;
3156 | | bytes32 m1;
3157 | | bytes32 m2;
3158 | | bytes32 m3;
3159 | | bytes32 m4;
3160 | | /// @solidity memory-safe-assembly
3161 | | assembly {
3162 | | m0 := mload(0x00)
3163 | | m1 := mload(0x20)
3164 | | m2 := mload(0x40)
3165 | | m3 := mload(0x60)
3166 | | m4 := mload(0x80)
3167 | | // Selector of `log(address,address,bool,bool)`.
3168 | | mstore(0x00, 0x2cd4134a)
3169 | | mstore(0x20, p0)
3170 | | mstore(0x40, p1)
3171 | | mstore(0x60, p2)
3172 | | mstore(0x80, p3)
3173 | | }
3174 | | _sendLogPayload(0x1c, 0x84);
3175 | | /// @solidity memory-safe-assembly
3176 | | assembly {
3177 | | mstore(0x00, m0)
3178 | | mstore(0x20, m1)
3179 | | mstore(0x40, m2)
3180 | | mstore(0x60, m3)
3181 | | mstore(0x80, m4)
3182 | | }
3183 | | }
3184 | |
3185 | | function log(address p0, address p1, bool p2, uint256 p3) internal pure {
3186 | | bytes32 m0;
3187 | | bytes32 m1;
3188 | | bytes32 m2;
3189 | | bytes32 m3;
3190 | | bytes32 m4;
3191 | | /// @solidity memory-safe-assembly
3192 | | assembly {
3193 | | m0 := mload(0x00)
3194 | | m1 := mload(0x20)
3195 | | m2 := mload(0x40)
3196 | | m3 := mload(0x60)
3197 | | m4 := mload(0x80)
3198 | | // Selector of `log(address,address,bool,uint256)`.
3199 | | mstore(0x00, 0x3971e78c)
3200 | | mstore(0x20, p0)
3201 | | mstore(0x40, p1)
3202 | | mstore(0x60, p2)
3203 | | mstore(0x80, p3)
3204 | | }
3205 | | _sendLogPayload(0x1c, 0x84);
3206 | | /// @solidity memory-safe-assembly
3207 | | assembly {
3208 | | mstore(0x00, m0)
3209 | | mstore(0x20, m1)
3210 | | mstore(0x40, m2)
3211 | | mstore(0x60, m3)
3212 | | mstore(0x80, m4)
3213 | | }
3214 | | }
3215 | |
3216 | | function log(address p0, address p1, bool p2, bytes32 p3) internal pure {
3217 | | bytes32 m0;
3218 | | bytes32 m1;
3219 | | bytes32 m2;
3220 | | bytes32 m3;
3221 | | bytes32 m4;
3222 | | bytes32 m5;
3223 | | bytes32 m6;
3224 | | /// @solidity memory-safe-assembly
3225 | | assembly {
3226 | | function writeString(pos, w) {
3227 | | let length := 0
3228 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3229 | | mstore(pos, length)
3230 | | let shift := sub(256, shl(3, length))
3231 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3232 | | }
3233 | | m0 := mload(0x00)
3234 | | m1 := mload(0x20)
3235 | | m2 := mload(0x40)
3236 | | m3 := mload(0x60)
3237 | | m4 := mload(0x80)
3238 | | m5 := mload(0xa0)
3239 | | m6 := mload(0xc0)
3240 | | // Selector of `log(address,address,bool,string)`.
3241 | | mstore(0x00, 0xaa6540c8)
3242 | | mstore(0x20, p0)
3243 | | mstore(0x40, p1)
3244 | | mstore(0x60, p2)
3245 | | mstore(0x80, 0x80)
3246 | | writeString(0xa0, p3)
3247 | | }
3248 | | _sendLogPayload(0x1c, 0xc4);
3249 | | /// @solidity memory-safe-assembly
3250 | | assembly {
3251 | | mstore(0x00, m0)
3252 | | mstore(0x20, m1)
3253 | | mstore(0x40, m2)
3254 | | mstore(0x60, m3)
3255 | | mstore(0x80, m4)
3256 | | mstore(0xa0, m5)
3257 | | mstore(0xc0, m6)
3258 | | }
3259 | | }
3260 | |
3261 | | function log(address p0, address p1, uint256 p2, address p3) internal pure {
3262 | | bytes32 m0;
3263 | | bytes32 m1;
3264 | | bytes32 m2;
3265 | | bytes32 m3;
3266 | | bytes32 m4;
3267 | | /// @solidity memory-safe-assembly
3268 | | assembly {
3269 | | m0 := mload(0x00)
3270 | | m1 := mload(0x20)
3271 | | m2 := mload(0x40)
3272 | | m3 := mload(0x60)
3273 | | m4 := mload(0x80)
3274 | | // Selector of `log(address,address,uint256,address)`.
3275 | | mstore(0x00, 0x8da6def5)
3276 | | mstore(0x20, p0)
3277 | | mstore(0x40, p1)
3278 | | mstore(0x60, p2)
3279 | | mstore(0x80, p3)
3280 | | }
3281 | | _sendLogPayload(0x1c, 0x84);
3282 | | /// @solidity memory-safe-assembly
3283 | | assembly {
3284 | | mstore(0x00, m0)
3285 | | mstore(0x20, m1)
3286 | | mstore(0x40, m2)
3287 | | mstore(0x60, m3)
3288 | | mstore(0x80, m4)
3289 | | }
3290 | | }
3291 | |
3292 | | function log(address p0, address p1, uint256 p2, bool p3) internal pure {
3293 | | bytes32 m0;
3294 | | bytes32 m1;
3295 | | bytes32 m2;
3296 | | bytes32 m3;
3297 | | bytes32 m4;
3298 | | /// @solidity memory-safe-assembly
3299 | | assembly {
3300 | | m0 := mload(0x00)
3301 | | m1 := mload(0x20)
3302 | | m2 := mload(0x40)
3303 | | m3 := mload(0x60)
3304 | | m4 := mload(0x80)
3305 | | // Selector of `log(address,address,uint256,bool)`.
3306 | | mstore(0x00, 0x9b4254e2)
3307 | | mstore(0x20, p0)
3308 | | mstore(0x40, p1)
3309 | | mstore(0x60, p2)
3310 | | mstore(0x80, p3)
3311 | | }
3312 | | _sendLogPayload(0x1c, 0x84);
3313 | | /// @solidity memory-safe-assembly
3314 | | assembly {
3315 | | mstore(0x00, m0)
3316 | | mstore(0x20, m1)
3317 | | mstore(0x40, m2)
3318 | | mstore(0x60, m3)
3319 | | mstore(0x80, m4)
3320 | | }
3321 | | }
3322 | |
3323 | | function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
3324 | | bytes32 m0;
3325 | | bytes32 m1;
3326 | | bytes32 m2;
3327 | | bytes32 m3;
3328 | | bytes32 m4;
3329 | | /// @solidity memory-safe-assembly
3330 | | assembly {
3331 | | m0 := mload(0x00)
3332 | | m1 := mload(0x20)
3333 | | m2 := mload(0x40)
3334 | | m3 := mload(0x60)
3335 | | m4 := mload(0x80)
3336 | | // Selector of `log(address,address,uint256,uint256)`.
3337 | | mstore(0x00, 0xbe553481)
3338 | | mstore(0x20, p0)
3339 | | mstore(0x40, p1)
3340 | | mstore(0x60, p2)
3341 | | mstore(0x80, p3)
3342 | | }
3343 | | _sendLogPayload(0x1c, 0x84);
3344 | | /// @solidity memory-safe-assembly
3345 | | assembly {
3346 | | mstore(0x00, m0)
3347 | | mstore(0x20, m1)
3348 | | mstore(0x40, m2)
3349 | | mstore(0x60, m3)
3350 | | mstore(0x80, m4)
3351 | | }
3352 | | }
3353 | |
3354 | | function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure {
3355 | | bytes32 m0;
3356 | | bytes32 m1;
3357 | | bytes32 m2;
3358 | | bytes32 m3;
3359 | | bytes32 m4;
3360 | | bytes32 m5;
3361 | | bytes32 m6;
3362 | | /// @solidity memory-safe-assembly
3363 | | assembly {
3364 | | function writeString(pos, w) {
3365 | | let length := 0
3366 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3367 | | mstore(pos, length)
3368 | | let shift := sub(256, shl(3, length))
3369 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3370 | | }
3371 | | m0 := mload(0x00)
3372 | | m1 := mload(0x20)
3373 | | m2 := mload(0x40)
3374 | | m3 := mload(0x60)
3375 | | m4 := mload(0x80)
3376 | | m5 := mload(0xa0)
3377 | | m6 := mload(0xc0)
3378 | | // Selector of `log(address,address,uint256,string)`.
3379 | | mstore(0x00, 0xfdb4f990)
3380 | | mstore(0x20, p0)
3381 | | mstore(0x40, p1)
3382 | | mstore(0x60, p2)
3383 | | mstore(0x80, 0x80)
3384 | | writeString(0xa0, p3)
3385 | | }
3386 | | _sendLogPayload(0x1c, 0xc4);
3387 | | /// @solidity memory-safe-assembly
3388 | | assembly {
3389 | | mstore(0x00, m0)
3390 | | mstore(0x20, m1)
3391 | | mstore(0x40, m2)
3392 | | mstore(0x60, m3)
3393 | | mstore(0x80, m4)
3394 | | mstore(0xa0, m5)
3395 | | mstore(0xc0, m6)
3396 | | }
3397 | | }
3398 | |
3399 | | function log(address p0, address p1, bytes32 p2, address p3) internal pure {
3400 | | bytes32 m0;
3401 | | bytes32 m1;
3402 | | bytes32 m2;
3403 | | bytes32 m3;
3404 | | bytes32 m4;
3405 | | bytes32 m5;
3406 | | bytes32 m6;
3407 | | /// @solidity memory-safe-assembly
3408 | | assembly {
3409 | | function writeString(pos, w) {
3410 | | let length := 0
3411 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3412 | | mstore(pos, length)
3413 | | let shift := sub(256, shl(3, length))
3414 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3415 | | }
3416 | | m0 := mload(0x00)
3417 | | m1 := mload(0x20)
3418 | | m2 := mload(0x40)
3419 | | m3 := mload(0x60)
3420 | | m4 := mload(0x80)
3421 | | m5 := mload(0xa0)
3422 | | m6 := mload(0xc0)
3423 | | // Selector of `log(address,address,string,address)`.
3424 | | mstore(0x00, 0x8f736d16)
3425 | | mstore(0x20, p0)
3426 | | mstore(0x40, p1)
3427 | | mstore(0x60, 0x80)
3428 | | mstore(0x80, p3)
3429 | | writeString(0xa0, p2)
3430 | | }
3431 | | _sendLogPayload(0x1c, 0xc4);
3432 | | /// @solidity memory-safe-assembly
3433 | | assembly {
3434 | | mstore(0x00, m0)
3435 | | mstore(0x20, m1)
3436 | | mstore(0x40, m2)
3437 | | mstore(0x60, m3)
3438 | | mstore(0x80, m4)
3439 | | mstore(0xa0, m5)
3440 | | mstore(0xc0, m6)
3441 | | }
3442 | | }
3443 | |
3444 | | function log(address p0, address p1, bytes32 p2, bool p3) internal pure {
3445 | | bytes32 m0;
3446 | | bytes32 m1;
3447 | | bytes32 m2;
3448 | | bytes32 m3;
3449 | | bytes32 m4;
3450 | | bytes32 m5;
3451 | | bytes32 m6;
3452 | | /// @solidity memory-safe-assembly
3453 | | assembly {
3454 | | function writeString(pos, w) {
3455 | | let length := 0
3456 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3457 | | mstore(pos, length)
3458 | | let shift := sub(256, shl(3, length))
3459 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3460 | | }
3461 | | m0 := mload(0x00)
3462 | | m1 := mload(0x20)
3463 | | m2 := mload(0x40)
3464 | | m3 := mload(0x60)
3465 | | m4 := mload(0x80)
3466 | | m5 := mload(0xa0)
3467 | | m6 := mload(0xc0)
3468 | | // Selector of `log(address,address,string,bool)`.
3469 | | mstore(0x00, 0x6f1a594e)
3470 | | mstore(0x20, p0)
3471 | | mstore(0x40, p1)
3472 | | mstore(0x60, 0x80)
3473 | | mstore(0x80, p3)
3474 | | writeString(0xa0, p2)
3475 | | }
3476 | | _sendLogPayload(0x1c, 0xc4);
3477 | | /// @solidity memory-safe-assembly
3478 | | assembly {
3479 | | mstore(0x00, m0)
3480 | | mstore(0x20, m1)
3481 | | mstore(0x40, m2)
3482 | | mstore(0x60, m3)
3483 | | mstore(0x80, m4)
3484 | | mstore(0xa0, m5)
3485 | | mstore(0xc0, m6)
3486 | | }
3487 | | }
3488 | |
3489 | | function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure {
3490 | | bytes32 m0;
3491 | | bytes32 m1;
3492 | | bytes32 m2;
3493 | | bytes32 m3;
3494 | | bytes32 m4;
3495 | | bytes32 m5;
3496 | | bytes32 m6;
3497 | | /// @solidity memory-safe-assembly
3498 | | assembly {
3499 | | function writeString(pos, w) {
3500 | | let length := 0
3501 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3502 | | mstore(pos, length)
3503 | | let shift := sub(256, shl(3, length))
3504 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3505 | | }
3506 | | m0 := mload(0x00)
3507 | | m1 := mload(0x20)
3508 | | m2 := mload(0x40)
3509 | | m3 := mload(0x60)
3510 | | m4 := mload(0x80)
3511 | | m5 := mload(0xa0)
3512 | | m6 := mload(0xc0)
3513 | | // Selector of `log(address,address,string,uint256)`.
3514 | | mstore(0x00, 0xef1cefe7)
3515 | | mstore(0x20, p0)
3516 | | mstore(0x40, p1)
3517 | | mstore(0x60, 0x80)
3518 | | mstore(0x80, p3)
3519 | | writeString(0xa0, p2)
3520 | | }
3521 | | _sendLogPayload(0x1c, 0xc4);
3522 | | /// @solidity memory-safe-assembly
3523 | | assembly {
3524 | | mstore(0x00, m0)
3525 | | mstore(0x20, m1)
3526 | | mstore(0x40, m2)
3527 | | mstore(0x60, m3)
3528 | | mstore(0x80, m4)
3529 | | mstore(0xa0, m5)
3530 | | mstore(0xc0, m6)
3531 | | }
3532 | | }
3533 | |
3534 | | function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure {
3535 | | bytes32 m0;
3536 | | bytes32 m1;
3537 | | bytes32 m2;
3538 | | bytes32 m3;
3539 | | bytes32 m4;
3540 | | bytes32 m5;
3541 | | bytes32 m6;
3542 | | bytes32 m7;
3543 | | bytes32 m8;
3544 | | /// @solidity memory-safe-assembly
3545 | | assembly {
3546 | | function writeString(pos, w) {
3547 | | let length := 0
3548 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3549 | | mstore(pos, length)
3550 | | let shift := sub(256, shl(3, length))
3551 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3552 | | }
3553 | | m0 := mload(0x00)
3554 | | m1 := mload(0x20)
3555 | | m2 := mload(0x40)
3556 | | m3 := mload(0x60)
3557 | | m4 := mload(0x80)
3558 | | m5 := mload(0xa0)
3559 | | m6 := mload(0xc0)
3560 | | m7 := mload(0xe0)
3561 | | m8 := mload(0x100)
3562 | | // Selector of `log(address,address,string,string)`.
3563 | | mstore(0x00, 0x21bdaf25)
3564 | | mstore(0x20, p0)
3565 | | mstore(0x40, p1)
3566 | | mstore(0x60, 0x80)
3567 | | mstore(0x80, 0xc0)
3568 | | writeString(0xa0, p2)
3569 | | writeString(0xe0, p3)
3570 | | }
3571 | | _sendLogPayload(0x1c, 0x104);
3572 | | /// @solidity memory-safe-assembly
3573 | | assembly {
3574 | | mstore(0x00, m0)
3575 | | mstore(0x20, m1)
3576 | | mstore(0x40, m2)
3577 | | mstore(0x60, m3)
3578 | | mstore(0x80, m4)
3579 | | mstore(0xa0, m5)
3580 | | mstore(0xc0, m6)
3581 | | mstore(0xe0, m7)
3582 | | mstore(0x100, m8)
3583 | | }
3584 | | }
3585 | |
3586 | | function log(address p0, bool p1, address p2, address p3) internal pure {
3587 | | bytes32 m0;
3588 | | bytes32 m1;
3589 | | bytes32 m2;
3590 | | bytes32 m3;
3591 | | bytes32 m4;
3592 | | /// @solidity memory-safe-assembly
3593 | | assembly {
3594 | | m0 := mload(0x00)
3595 | | m1 := mload(0x20)
3596 | | m2 := mload(0x40)
3597 | | m3 := mload(0x60)
3598 | | m4 := mload(0x80)
3599 | | // Selector of `log(address,bool,address,address)`.
3600 | | mstore(0x00, 0x660375dd)
3601 | | mstore(0x20, p0)
3602 | | mstore(0x40, p1)
3603 | | mstore(0x60, p2)
3604 | | mstore(0x80, p3)
3605 | | }
3606 | | _sendLogPayload(0x1c, 0x84);
3607 | | /// @solidity memory-safe-assembly
3608 | | assembly {
3609 | | mstore(0x00, m0)
3610 | | mstore(0x20, m1)
3611 | | mstore(0x40, m2)
3612 | | mstore(0x60, m3)
3613 | | mstore(0x80, m4)
3614 | | }
3615 | | }
3616 | |
3617 | | function log(address p0, bool p1, address p2, bool p3) internal pure {
3618 | | bytes32 m0;
3619 | | bytes32 m1;
3620 | | bytes32 m2;
3621 | | bytes32 m3;
3622 | | bytes32 m4;
3623 | | /// @solidity memory-safe-assembly
3624 | | assembly {
3625 | | m0 := mload(0x00)
3626 | | m1 := mload(0x20)
3627 | | m2 := mload(0x40)
3628 | | m3 := mload(0x60)
3629 | | m4 := mload(0x80)
3630 | | // Selector of `log(address,bool,address,bool)`.
3631 | | mstore(0x00, 0xa6f50b0f)
3632 | | mstore(0x20, p0)
3633 | | mstore(0x40, p1)
3634 | | mstore(0x60, p2)
3635 | | mstore(0x80, p3)
3636 | | }
3637 | | _sendLogPayload(0x1c, 0x84);
3638 | | /// @solidity memory-safe-assembly
3639 | | assembly {
3640 | | mstore(0x00, m0)
3641 | | mstore(0x20, m1)
3642 | | mstore(0x40, m2)
3643 | | mstore(0x60, m3)
3644 | | mstore(0x80, m4)
3645 | | }
3646 | | }
3647 | |
3648 | | function log(address p0, bool p1, address p2, uint256 p3) internal pure {
3649 | | bytes32 m0;
3650 | | bytes32 m1;
3651 | | bytes32 m2;
3652 | | bytes32 m3;
3653 | | bytes32 m4;
3654 | | /// @solidity memory-safe-assembly
3655 | | assembly {
3656 | | m0 := mload(0x00)
3657 | | m1 := mload(0x20)
3658 | | m2 := mload(0x40)
3659 | | m3 := mload(0x60)
3660 | | m4 := mload(0x80)
3661 | | // Selector of `log(address,bool,address,uint256)`.
3662 | | mstore(0x00, 0xa75c59de)
3663 | | mstore(0x20, p0)
3664 | | mstore(0x40, p1)
3665 | | mstore(0x60, p2)
3666 | | mstore(0x80, p3)
3667 | | }
3668 | | _sendLogPayload(0x1c, 0x84);
3669 | | /// @solidity memory-safe-assembly
3670 | | assembly {
3671 | | mstore(0x00, m0)
3672 | | mstore(0x20, m1)
3673 | | mstore(0x40, m2)
3674 | | mstore(0x60, m3)
3675 | | mstore(0x80, m4)
3676 | | }
3677 | | }
3678 | |
3679 | | function log(address p0, bool p1, address p2, bytes32 p3) internal pure {
3680 | | bytes32 m0;
3681 | | bytes32 m1;
3682 | | bytes32 m2;
3683 | | bytes32 m3;
3684 | | bytes32 m4;
3685 | | bytes32 m5;
3686 | | bytes32 m6;
3687 | | /// @solidity memory-safe-assembly
3688 | | assembly {
3689 | | function writeString(pos, w) {
3690 | | let length := 0
3691 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3692 | | mstore(pos, length)
3693 | | let shift := sub(256, shl(3, length))
3694 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3695 | | }
3696 | | m0 := mload(0x00)
3697 | | m1 := mload(0x20)
3698 | | m2 := mload(0x40)
3699 | | m3 := mload(0x60)
3700 | | m4 := mload(0x80)
3701 | | m5 := mload(0xa0)
3702 | | m6 := mload(0xc0)
3703 | | // Selector of `log(address,bool,address,string)`.
3704 | | mstore(0x00, 0x2dd778e6)
3705 | | mstore(0x20, p0)
3706 | | mstore(0x40, p1)
3707 | | mstore(0x60, p2)
3708 | | mstore(0x80, 0x80)
3709 | | writeString(0xa0, p3)
3710 | | }
3711 | | _sendLogPayload(0x1c, 0xc4);
3712 | | /// @solidity memory-safe-assembly
3713 | | assembly {
3714 | | mstore(0x00, m0)
3715 | | mstore(0x20, m1)
3716 | | mstore(0x40, m2)
3717 | | mstore(0x60, m3)
3718 | | mstore(0x80, m4)
3719 | | mstore(0xa0, m5)
3720 | | mstore(0xc0, m6)
3721 | | }
3722 | | }
3723 | |
3724 | | function log(address p0, bool p1, bool p2, address p3) internal pure {
3725 | | bytes32 m0;
3726 | | bytes32 m1;
3727 | | bytes32 m2;
3728 | | bytes32 m3;
3729 | | bytes32 m4;
3730 | | /// @solidity memory-safe-assembly
3731 | | assembly {
3732 | | m0 := mload(0x00)
3733 | | m1 := mload(0x20)
3734 | | m2 := mload(0x40)
3735 | | m3 := mload(0x60)
3736 | | m4 := mload(0x80)
3737 | | // Selector of `log(address,bool,bool,address)`.
3738 | | mstore(0x00, 0xcf394485)
3739 | | mstore(0x20, p0)
3740 | | mstore(0x40, p1)
3741 | | mstore(0x60, p2)
3742 | | mstore(0x80, p3)
3743 | | }
3744 | | _sendLogPayload(0x1c, 0x84);
3745 | | /// @solidity memory-safe-assembly
3746 | | assembly {
3747 | | mstore(0x00, m0)
3748 | | mstore(0x20, m1)
3749 | | mstore(0x40, m2)
3750 | | mstore(0x60, m3)
3751 | | mstore(0x80, m4)
3752 | | }
3753 | | }
3754 | |
3755 | | function log(address p0, bool p1, bool p2, bool p3) internal pure {
3756 | | bytes32 m0;
3757 | | bytes32 m1;
3758 | | bytes32 m2;
3759 | | bytes32 m3;
3760 | | bytes32 m4;
3761 | | /// @solidity memory-safe-assembly
3762 | | assembly {
3763 | | m0 := mload(0x00)
3764 | | m1 := mload(0x20)
3765 | | m2 := mload(0x40)
3766 | | m3 := mload(0x60)
3767 | | m4 := mload(0x80)
3768 | | // Selector of `log(address,bool,bool,bool)`.
3769 | | mstore(0x00, 0xcac43479)
3770 | | mstore(0x20, p0)
3771 | | mstore(0x40, p1)
3772 | | mstore(0x60, p2)
3773 | | mstore(0x80, p3)
3774 | | }
3775 | | _sendLogPayload(0x1c, 0x84);
3776 | | /// @solidity memory-safe-assembly
3777 | | assembly {
3778 | | mstore(0x00, m0)
3779 | | mstore(0x20, m1)
3780 | | mstore(0x40, m2)
3781 | | mstore(0x60, m3)
3782 | | mstore(0x80, m4)
3783 | | }
3784 | | }
3785 | |
3786 | | function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
3787 | | bytes32 m0;
3788 | | bytes32 m1;
3789 | | bytes32 m2;
3790 | | bytes32 m3;
3791 | | bytes32 m4;
3792 | | /// @solidity memory-safe-assembly
3793 | | assembly {
3794 | | m0 := mload(0x00)
3795 | | m1 := mload(0x20)
3796 | | m2 := mload(0x40)
3797 | | m3 := mload(0x60)
3798 | | m4 := mload(0x80)
3799 | | // Selector of `log(address,bool,bool,uint256)`.
3800 | | mstore(0x00, 0x8c4e5de6)
3801 | | mstore(0x20, p0)
3802 | | mstore(0x40, p1)
3803 | | mstore(0x60, p2)
3804 | | mstore(0x80, p3)
3805 | | }
3806 | | _sendLogPayload(0x1c, 0x84);
3807 | | /// @solidity memory-safe-assembly
3808 | | assembly {
3809 | | mstore(0x00, m0)
3810 | | mstore(0x20, m1)
3811 | | mstore(0x40, m2)
3812 | | mstore(0x60, m3)
3813 | | mstore(0x80, m4)
3814 | | }
3815 | | }
3816 | |
3817 | | function log(address p0, bool p1, bool p2, bytes32 p3) internal pure {
3818 | | bytes32 m0;
3819 | | bytes32 m1;
3820 | | bytes32 m2;
3821 | | bytes32 m3;
3822 | | bytes32 m4;
3823 | | bytes32 m5;
3824 | | bytes32 m6;
3825 | | /// @solidity memory-safe-assembly
3826 | | assembly {
3827 | | function writeString(pos, w) {
3828 | | let length := 0
3829 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3830 | | mstore(pos, length)
3831 | | let shift := sub(256, shl(3, length))
3832 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3833 | | }
3834 | | m0 := mload(0x00)
3835 | | m1 := mload(0x20)
3836 | | m2 := mload(0x40)
3837 | | m3 := mload(0x60)
3838 | | m4 := mload(0x80)
3839 | | m5 := mload(0xa0)
3840 | | m6 := mload(0xc0)
3841 | | // Selector of `log(address,bool,bool,string)`.
3842 | | mstore(0x00, 0xdfc4a2e8)
3843 | | mstore(0x20, p0)
3844 | | mstore(0x40, p1)
3845 | | mstore(0x60, p2)
3846 | | mstore(0x80, 0x80)
3847 | | writeString(0xa0, p3)
3848 | | }
3849 | | _sendLogPayload(0x1c, 0xc4);
3850 | | /// @solidity memory-safe-assembly
3851 | | assembly {
3852 | | mstore(0x00, m0)
3853 | | mstore(0x20, m1)
3854 | | mstore(0x40, m2)
3855 | | mstore(0x60, m3)
3856 | | mstore(0x80, m4)
3857 | | mstore(0xa0, m5)
3858 | | mstore(0xc0, m6)
3859 | | }
3860 | | }
3861 | |
3862 | | function log(address p0, bool p1, uint256 p2, address p3) internal pure {
3863 | | bytes32 m0;
3864 | | bytes32 m1;
3865 | | bytes32 m2;
3866 | | bytes32 m3;
3867 | | bytes32 m4;
3868 | | /// @solidity memory-safe-assembly
3869 | | assembly {
3870 | | m0 := mload(0x00)
3871 | | m1 := mload(0x20)
3872 | | m2 := mload(0x40)
3873 | | m3 := mload(0x60)
3874 | | m4 := mload(0x80)
3875 | | // Selector of `log(address,bool,uint256,address)`.
3876 | | mstore(0x00, 0xccf790a1)
3877 | | mstore(0x20, p0)
3878 | | mstore(0x40, p1)
3879 | | mstore(0x60, p2)
3880 | | mstore(0x80, p3)
3881 | | }
3882 | | _sendLogPayload(0x1c, 0x84);
3883 | | /// @solidity memory-safe-assembly
3884 | | assembly {
3885 | | mstore(0x00, m0)
3886 | | mstore(0x20, m1)
3887 | | mstore(0x40, m2)
3888 | | mstore(0x60, m3)
3889 | | mstore(0x80, m4)
3890 | | }
3891 | | }
3892 | |
3893 | | function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
3894 | | bytes32 m0;
3895 | | bytes32 m1;
3896 | | bytes32 m2;
3897 | | bytes32 m3;
3898 | | bytes32 m4;
3899 | | /// @solidity memory-safe-assembly
3900 | | assembly {
3901 | | m0 := mload(0x00)
3902 | | m1 := mload(0x20)
3903 | | m2 := mload(0x40)
3904 | | m3 := mload(0x60)
3905 | | m4 := mload(0x80)
3906 | | // Selector of `log(address,bool,uint256,bool)`.
3907 | | mstore(0x00, 0xc4643e20)
3908 | | mstore(0x20, p0)
3909 | | mstore(0x40, p1)
3910 | | mstore(0x60, p2)
3911 | | mstore(0x80, p3)
3912 | | }
3913 | | _sendLogPayload(0x1c, 0x84);
3914 | | /// @solidity memory-safe-assembly
3915 | | assembly {
3916 | | mstore(0x00, m0)
3917 | | mstore(0x20, m1)
3918 | | mstore(0x40, m2)
3919 | | mstore(0x60, m3)
3920 | | mstore(0x80, m4)
3921 | | }
3922 | | }
3923 | |
3924 | | function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
3925 | | bytes32 m0;
3926 | | bytes32 m1;
3927 | | bytes32 m2;
3928 | | bytes32 m3;
3929 | | bytes32 m4;
3930 | | /// @solidity memory-safe-assembly
3931 | | assembly {
3932 | | m0 := mload(0x00)
3933 | | m1 := mload(0x20)
3934 | | m2 := mload(0x40)
3935 | | m3 := mload(0x60)
3936 | | m4 := mload(0x80)
3937 | | // Selector of `log(address,bool,uint256,uint256)`.
3938 | | mstore(0x00, 0x386ff5f4)
3939 | | mstore(0x20, p0)
3940 | | mstore(0x40, p1)
3941 | | mstore(0x60, p2)
3942 | | mstore(0x80, p3)
3943 | | }
3944 | | _sendLogPayload(0x1c, 0x84);
3945 | | /// @solidity memory-safe-assembly
3946 | | assembly {
3947 | | mstore(0x00, m0)
3948 | | mstore(0x20, m1)
3949 | | mstore(0x40, m2)
3950 | | mstore(0x60, m3)
3951 | | mstore(0x80, m4)
3952 | | }
3953 | | }
3954 | |
3955 | | function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure {
3956 | | bytes32 m0;
3957 | | bytes32 m1;
3958 | | bytes32 m2;
3959 | | bytes32 m3;
3960 | | bytes32 m4;
3961 | | bytes32 m5;
3962 | | bytes32 m6;
3963 | | /// @solidity memory-safe-assembly
3964 | | assembly {
3965 | | function writeString(pos, w) {
3966 | | let length := 0
3967 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3968 | | mstore(pos, length)
3969 | | let shift := sub(256, shl(3, length))
3970 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3971 | | }
3972 | | m0 := mload(0x00)
3973 | | m1 := mload(0x20)
3974 | | m2 := mload(0x40)
3975 | | m3 := mload(0x60)
3976 | | m4 := mload(0x80)
3977 | | m5 := mload(0xa0)
3978 | | m6 := mload(0xc0)
3979 | | // Selector of `log(address,bool,uint256,string)`.
3980 | | mstore(0x00, 0x0aa6cfad)
3981 | | mstore(0x20, p0)
3982 | | mstore(0x40, p1)
3983 | | mstore(0x60, p2)
3984 | | mstore(0x80, 0x80)
3985 | | writeString(0xa0, p3)
3986 | | }
3987 | | _sendLogPayload(0x1c, 0xc4);
3988 | | /// @solidity memory-safe-assembly
3989 | | assembly {
3990 | | mstore(0x00, m0)
3991 | | mstore(0x20, m1)
3992 | | mstore(0x40, m2)
3993 | | mstore(0x60, m3)
3994 | | mstore(0x80, m4)
3995 | | mstore(0xa0, m5)
3996 | | mstore(0xc0, m6)
3997 | | }
3998 | | }
3999 | |
4000 | | function log(address p0, bool p1, bytes32 p2, address p3) internal pure {
4001 | | bytes32 m0;
4002 | | bytes32 m1;
4003 | | bytes32 m2;
4004 | | bytes32 m3;
4005 | | bytes32 m4;
4006 | | bytes32 m5;
4007 | | bytes32 m6;
4008 | | /// @solidity memory-safe-assembly
4009 | | assembly {
4010 | | function writeString(pos, w) {
4011 | | let length := 0
4012 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4013 | | mstore(pos, length)
4014 | | let shift := sub(256, shl(3, length))
4015 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4016 | | }
4017 | | m0 := mload(0x00)
4018 | | m1 := mload(0x20)
4019 | | m2 := mload(0x40)
4020 | | m3 := mload(0x60)
4021 | | m4 := mload(0x80)
4022 | | m5 := mload(0xa0)
4023 | | m6 := mload(0xc0)
4024 | | // Selector of `log(address,bool,string,address)`.
4025 | | mstore(0x00, 0x19fd4956)
4026 | | mstore(0x20, p0)
4027 | | mstore(0x40, p1)
4028 | | mstore(0x60, 0x80)
4029 | | mstore(0x80, p3)
4030 | | writeString(0xa0, p2)
4031 | | }
4032 | | _sendLogPayload(0x1c, 0xc4);
4033 | | /// @solidity memory-safe-assembly
4034 | | assembly {
4035 | | mstore(0x00, m0)
4036 | | mstore(0x20, m1)
4037 | | mstore(0x40, m2)
4038 | | mstore(0x60, m3)
4039 | | mstore(0x80, m4)
4040 | | mstore(0xa0, m5)
4041 | | mstore(0xc0, m6)
4042 | | }
4043 | | }
4044 | |
4045 | | function log(address p0, bool p1, bytes32 p2, bool p3) internal pure {
4046 | | bytes32 m0;
4047 | | bytes32 m1;
4048 | | bytes32 m2;
4049 | | bytes32 m3;
4050 | | bytes32 m4;
4051 | | bytes32 m5;
4052 | | bytes32 m6;
4053 | | /// @solidity memory-safe-assembly
4054 | | assembly {
4055 | | function writeString(pos, w) {
4056 | | let length := 0
4057 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4058 | | mstore(pos, length)
4059 | | let shift := sub(256, shl(3, length))
4060 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4061 | | }
4062 | | m0 := mload(0x00)
4063 | | m1 := mload(0x20)
4064 | | m2 := mload(0x40)
4065 | | m3 := mload(0x60)
4066 | | m4 := mload(0x80)
4067 | | m5 := mload(0xa0)
4068 | | m6 := mload(0xc0)
4069 | | // Selector of `log(address,bool,string,bool)`.
4070 | | mstore(0x00, 0x50ad461d)
4071 | | mstore(0x20, p0)
4072 | | mstore(0x40, p1)
4073 | | mstore(0x60, 0x80)
4074 | | mstore(0x80, p3)
4075 | | writeString(0xa0, p2)
4076 | | }
4077 | | _sendLogPayload(0x1c, 0xc4);
4078 | | /// @solidity memory-safe-assembly
4079 | | assembly {
4080 | | mstore(0x00, m0)
4081 | | mstore(0x20, m1)
4082 | | mstore(0x40, m2)
4083 | | mstore(0x60, m3)
4084 | | mstore(0x80, m4)
4085 | | mstore(0xa0, m5)
4086 | | mstore(0xc0, m6)
4087 | | }
4088 | | }
4089 | |
4090 | | function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure {
4091 | | bytes32 m0;
4092 | | bytes32 m1;
4093 | | bytes32 m2;
4094 | | bytes32 m3;
4095 | | bytes32 m4;
4096 | | bytes32 m5;
4097 | | bytes32 m6;
4098 | | /// @solidity memory-safe-assembly
4099 | | assembly {
4100 | | function writeString(pos, w) {
4101 | | let length := 0
4102 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4103 | | mstore(pos, length)
4104 | | let shift := sub(256, shl(3, length))
4105 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4106 | | }
4107 | | m0 := mload(0x00)
4108 | | m1 := mload(0x20)
4109 | | m2 := mload(0x40)
4110 | | m3 := mload(0x60)
4111 | | m4 := mload(0x80)
4112 | | m5 := mload(0xa0)
4113 | | m6 := mload(0xc0)
4114 | | // Selector of `log(address,bool,string,uint256)`.
4115 | | mstore(0x00, 0x80e6a20b)
4116 | | mstore(0x20, p0)
4117 | | mstore(0x40, p1)
4118 | | mstore(0x60, 0x80)
4119 | | mstore(0x80, p3)
4120 | | writeString(0xa0, p2)
4121 | | }
4122 | | _sendLogPayload(0x1c, 0xc4);
4123 | | /// @solidity memory-safe-assembly
4124 | | assembly {
4125 | | mstore(0x00, m0)
4126 | | mstore(0x20, m1)
4127 | | mstore(0x40, m2)
4128 | | mstore(0x60, m3)
4129 | | mstore(0x80, m4)
4130 | | mstore(0xa0, m5)
4131 | | mstore(0xc0, m6)
4132 | | }
4133 | | }
4134 | |
4135 | | function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
4136 | | bytes32 m0;
4137 | | bytes32 m1;
4138 | | bytes32 m2;
4139 | | bytes32 m3;
4140 | | bytes32 m4;
4141 | | bytes32 m5;
4142 | | bytes32 m6;
4143 | | bytes32 m7;
4144 | | bytes32 m8;
4145 | | /// @solidity memory-safe-assembly
4146 | | assembly {
4147 | | function writeString(pos, w) {
4148 | | let length := 0
4149 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4150 | | mstore(pos, length)
4151 | | let shift := sub(256, shl(3, length))
4152 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4153 | | }
4154 | | m0 := mload(0x00)
4155 | | m1 := mload(0x20)
4156 | | m2 := mload(0x40)
4157 | | m3 := mload(0x60)
4158 | | m4 := mload(0x80)
4159 | | m5 := mload(0xa0)
4160 | | m6 := mload(0xc0)
4161 | | m7 := mload(0xe0)
4162 | | m8 := mload(0x100)
4163 | | // Selector of `log(address,bool,string,string)`.
4164 | | mstore(0x00, 0x475c5c33)
4165 | | mstore(0x20, p0)
4166 | | mstore(0x40, p1)
4167 | | mstore(0x60, 0x80)
4168 | | mstore(0x80, 0xc0)
4169 | | writeString(0xa0, p2)
4170 | | writeString(0xe0, p3)
4171 | | }
4172 | | _sendLogPayload(0x1c, 0x104);
4173 | | /// @solidity memory-safe-assembly
4174 | | assembly {
4175 | | mstore(0x00, m0)
4176 | | mstore(0x20, m1)
4177 | | mstore(0x40, m2)
4178 | | mstore(0x60, m3)
4179 | | mstore(0x80, m4)
4180 | | mstore(0xa0, m5)
4181 | | mstore(0xc0, m6)
4182 | | mstore(0xe0, m7)
4183 | | mstore(0x100, m8)
4184 | | }
4185 | | }
4186 | |
4187 | | function log(address p0, uint256 p1, address p2, address p3) internal pure {
4188 | | bytes32 m0;
4189 | | bytes32 m1;
4190 | | bytes32 m2;
4191 | | bytes32 m3;
4192 | | bytes32 m4;
4193 | | /// @solidity memory-safe-assembly
4194 | | assembly {
4195 | | m0 := mload(0x00)
4196 | | m1 := mload(0x20)
4197 | | m2 := mload(0x40)
4198 | | m3 := mload(0x60)
4199 | | m4 := mload(0x80)
4200 | | // Selector of `log(address,uint256,address,address)`.
4201 | | mstore(0x00, 0x478d1c62)
4202 | | mstore(0x20, p0)
4203 | | mstore(0x40, p1)
4204 | | mstore(0x60, p2)
4205 | | mstore(0x80, p3)
4206 | | }
4207 | | _sendLogPayload(0x1c, 0x84);
4208 | | /// @solidity memory-safe-assembly
4209 | | assembly {
4210 | | mstore(0x00, m0)
4211 | | mstore(0x20, m1)
4212 | | mstore(0x40, m2)
4213 | | mstore(0x60, m3)
4214 | | mstore(0x80, m4)
4215 | | }
4216 | | }
4217 | |
4218 | | function log(address p0, uint256 p1, address p2, bool p3) internal pure {
4219 | | bytes32 m0;
4220 | | bytes32 m1;
4221 | | bytes32 m2;
4222 | | bytes32 m3;
4223 | | bytes32 m4;
4224 | | /// @solidity memory-safe-assembly
4225 | | assembly {
4226 | | m0 := mload(0x00)
4227 | | m1 := mload(0x20)
4228 | | m2 := mload(0x40)
4229 | | m3 := mload(0x60)
4230 | | m4 := mload(0x80)
4231 | | // Selector of `log(address,uint256,address,bool)`.
4232 | | mstore(0x00, 0xa1bcc9b3)
4233 | | mstore(0x20, p0)
4234 | | mstore(0x40, p1)
4235 | | mstore(0x60, p2)
4236 | | mstore(0x80, p3)
4237 | | }
4238 | | _sendLogPayload(0x1c, 0x84);
4239 | | /// @solidity memory-safe-assembly
4240 | | assembly {
4241 | | mstore(0x00, m0)
4242 | | mstore(0x20, m1)
4243 | | mstore(0x40, m2)
4244 | | mstore(0x60, m3)
4245 | | mstore(0x80, m4)
4246 | | }
4247 | | }
4248 | |
4249 | | function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
4250 | | bytes32 m0;
4251 | | bytes32 m1;
4252 | | bytes32 m2;
4253 | | bytes32 m3;
4254 | | bytes32 m4;
4255 | | /// @solidity memory-safe-assembly
4256 | | assembly {
4257 | | m0 := mload(0x00)
4258 | | m1 := mload(0x20)
4259 | | m2 := mload(0x40)
4260 | | m3 := mload(0x60)
4261 | | m4 := mload(0x80)
4262 | | // Selector of `log(address,uint256,address,uint256)`.
4263 | | mstore(0x00, 0x100f650e)
4264 | | mstore(0x20, p0)
4265 | | mstore(0x40, p1)
4266 | | mstore(0x60, p2)
4267 | | mstore(0x80, p3)
4268 | | }
4269 | | _sendLogPayload(0x1c, 0x84);
4270 | | /// @solidity memory-safe-assembly
4271 | | assembly {
4272 | | mstore(0x00, m0)
4273 | | mstore(0x20, m1)
4274 | | mstore(0x40, m2)
4275 | | mstore(0x60, m3)
4276 | | mstore(0x80, m4)
4277 | | }
4278 | | }
4279 | |
4280 | | function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure {
4281 | | bytes32 m0;
4282 | | bytes32 m1;
4283 | | bytes32 m2;
4284 | | bytes32 m3;
4285 | | bytes32 m4;
4286 | | bytes32 m5;
4287 | | bytes32 m6;
4288 | | /// @solidity memory-safe-assembly
4289 | | assembly {
4290 | | function writeString(pos, w) {
4291 | | let length := 0
4292 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4293 | | mstore(pos, length)
4294 | | let shift := sub(256, shl(3, length))
4295 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4296 | | }
4297 | | m0 := mload(0x00)
4298 | | m1 := mload(0x20)
4299 | | m2 := mload(0x40)
4300 | | m3 := mload(0x60)
4301 | | m4 := mload(0x80)
4302 | | m5 := mload(0xa0)
4303 | | m6 := mload(0xc0)
4304 | | // Selector of `log(address,uint256,address,string)`.
4305 | | mstore(0x00, 0x1da986ea)
4306 | | mstore(0x20, p0)
4307 | | mstore(0x40, p1)
4308 | | mstore(0x60, p2)
4309 | | mstore(0x80, 0x80)
4310 | | writeString(0xa0, p3)
4311 | | }
4312 | | _sendLogPayload(0x1c, 0xc4);
4313 | | /// @solidity memory-safe-assembly
4314 | | assembly {
4315 | | mstore(0x00, m0)
4316 | | mstore(0x20, m1)
4317 | | mstore(0x40, m2)
4318 | | mstore(0x60, m3)
4319 | | mstore(0x80, m4)
4320 | | mstore(0xa0, m5)
4321 | | mstore(0xc0, m6)
4322 | | }
4323 | | }
4324 | |
4325 | | function log(address p0, uint256 p1, bool p2, address p3) internal pure {
4326 | | bytes32 m0;
4327 | | bytes32 m1;
4328 | | bytes32 m2;
4329 | | bytes32 m3;
4330 | | bytes32 m4;
4331 | | /// @solidity memory-safe-assembly
4332 | | assembly {
4333 | | m0 := mload(0x00)
4334 | | m1 := mload(0x20)
4335 | | m2 := mload(0x40)
4336 | | m3 := mload(0x60)
4337 | | m4 := mload(0x80)
4338 | | // Selector of `log(address,uint256,bool,address)`.
4339 | | mstore(0x00, 0xa31bfdcc)
4340 | | mstore(0x20, p0)
4341 | | mstore(0x40, p1)
4342 | | mstore(0x60, p2)
4343 | | mstore(0x80, p3)
4344 | | }
4345 | | _sendLogPayload(0x1c, 0x84);
4346 | | /// @solidity memory-safe-assembly
4347 | | assembly {
4348 | | mstore(0x00, m0)
4349 | | mstore(0x20, m1)
4350 | | mstore(0x40, m2)
4351 | | mstore(0x60, m3)
4352 | | mstore(0x80, m4)
4353 | | }
4354 | | }
4355 | |
4356 | | function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
4357 | | bytes32 m0;
4358 | | bytes32 m1;
4359 | | bytes32 m2;
4360 | | bytes32 m3;
4361 | | bytes32 m4;
4362 | | /// @solidity memory-safe-assembly
4363 | | assembly {
4364 | | m0 := mload(0x00)
4365 | | m1 := mload(0x20)
4366 | | m2 := mload(0x40)
4367 | | m3 := mload(0x60)
4368 | | m4 := mload(0x80)
4369 | | // Selector of `log(address,uint256,bool,bool)`.
4370 | | mstore(0x00, 0x3bf5e537)
4371 | | mstore(0x20, p0)
4372 | | mstore(0x40, p1)
4373 | | mstore(0x60, p2)
4374 | | mstore(0x80, p3)
4375 | | }
4376 | | _sendLogPayload(0x1c, 0x84);
4377 | | /// @solidity memory-safe-assembly
4378 | | assembly {
4379 | | mstore(0x00, m0)
4380 | | mstore(0x20, m1)
4381 | | mstore(0x40, m2)
4382 | | mstore(0x60, m3)
4383 | | mstore(0x80, m4)
4384 | | }
4385 | | }
4386 | |
4387 | | function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
4388 | | bytes32 m0;
4389 | | bytes32 m1;
4390 | | bytes32 m2;
4391 | | bytes32 m3;
4392 | | bytes32 m4;
4393 | | /// @solidity memory-safe-assembly
4394 | | assembly {
4395 | | m0 := mload(0x00)
4396 | | m1 := mload(0x20)
4397 | | m2 := mload(0x40)
4398 | | m3 := mload(0x60)
4399 | | m4 := mload(0x80)
4400 | | // Selector of `log(address,uint256,bool,uint256)`.
4401 | | mstore(0x00, 0x22f6b999)
4402 | | mstore(0x20, p0)
4403 | | mstore(0x40, p1)
4404 | | mstore(0x60, p2)
4405 | | mstore(0x80, p3)
4406 | | }
4407 | | _sendLogPayload(0x1c, 0x84);
4408 | | /// @solidity memory-safe-assembly
4409 | | assembly {
4410 | | mstore(0x00, m0)
4411 | | mstore(0x20, m1)
4412 | | mstore(0x40, m2)
4413 | | mstore(0x60, m3)
4414 | | mstore(0x80, m4)
4415 | | }
4416 | | }
4417 | |
4418 | | function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure {
4419 | | bytes32 m0;
4420 | | bytes32 m1;
4421 | | bytes32 m2;
4422 | | bytes32 m3;
4423 | | bytes32 m4;
4424 | | bytes32 m5;
4425 | | bytes32 m6;
4426 | | /// @solidity memory-safe-assembly
4427 | | assembly {
4428 | | function writeString(pos, w) {
4429 | | let length := 0
4430 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4431 | | mstore(pos, length)
4432 | | let shift := sub(256, shl(3, length))
4433 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4434 | | }
4435 | | m0 := mload(0x00)
4436 | | m1 := mload(0x20)
4437 | | m2 := mload(0x40)
4438 | | m3 := mload(0x60)
4439 | | m4 := mload(0x80)
4440 | | m5 := mload(0xa0)
4441 | | m6 := mload(0xc0)
4442 | | // Selector of `log(address,uint256,bool,string)`.
4443 | | mstore(0x00, 0xc5ad85f9)
4444 | | mstore(0x20, p0)
4445 | | mstore(0x40, p1)
4446 | | mstore(0x60, p2)
4447 | | mstore(0x80, 0x80)
4448 | | writeString(0xa0, p3)
4449 | | }
4450 | | _sendLogPayload(0x1c, 0xc4);
4451 | | /// @solidity memory-safe-assembly
4452 | | assembly {
4453 | | mstore(0x00, m0)
4454 | | mstore(0x20, m1)
4455 | | mstore(0x40, m2)
4456 | | mstore(0x60, m3)
4457 | | mstore(0x80, m4)
4458 | | mstore(0xa0, m5)
4459 | | mstore(0xc0, m6)
4460 | | }
4461 | | }
4462 | |
4463 | | function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
4464 | | bytes32 m0;
4465 | | bytes32 m1;
4466 | | bytes32 m2;
4467 | | bytes32 m3;
4468 | | bytes32 m4;
4469 | | /// @solidity memory-safe-assembly
4470 | | assembly {
4471 | | m0 := mload(0x00)
4472 | | m1 := mload(0x20)
4473 | | m2 := mload(0x40)
4474 | | m3 := mload(0x60)
4475 | | m4 := mload(0x80)
4476 | | // Selector of `log(address,uint256,uint256,address)`.
4477 | | mstore(0x00, 0x20e3984d)
4478 | | mstore(0x20, p0)
4479 | | mstore(0x40, p1)
4480 | | mstore(0x60, p2)
4481 | | mstore(0x80, p3)
4482 | | }
4483 | | _sendLogPayload(0x1c, 0x84);
4484 | | /// @solidity memory-safe-assembly
4485 | | assembly {
4486 | | mstore(0x00, m0)
4487 | | mstore(0x20, m1)
4488 | | mstore(0x40, m2)
4489 | | mstore(0x60, m3)
4490 | | mstore(0x80, m4)
4491 | | }
4492 | | }
4493 | |
4494 | | function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
4495 | | bytes32 m0;
4496 | | bytes32 m1;
4497 | | bytes32 m2;
4498 | | bytes32 m3;
4499 | | bytes32 m4;
4500 | | /// @solidity memory-safe-assembly
4501 | | assembly {
4502 | | m0 := mload(0x00)
4503 | | m1 := mload(0x20)
4504 | | m2 := mload(0x40)
4505 | | m3 := mload(0x60)
4506 | | m4 := mload(0x80)
4507 | | // Selector of `log(address,uint256,uint256,bool)`.
4508 | | mstore(0x00, 0x66f1bc67)
4509 | | mstore(0x20, p0)
4510 | | mstore(0x40, p1)
4511 | | mstore(0x60, p2)
4512 | | mstore(0x80, p3)
4513 | | }
4514 | | _sendLogPayload(0x1c, 0x84);
4515 | | /// @solidity memory-safe-assembly
4516 | | assembly {
4517 | | mstore(0x00, m0)
4518 | | mstore(0x20, m1)
4519 | | mstore(0x40, m2)
4520 | | mstore(0x60, m3)
4521 | | mstore(0x80, m4)
4522 | | }
4523 | | }
4524 | |
4525 | | function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
4526 | | bytes32 m0;
4527 | | bytes32 m1;
4528 | | bytes32 m2;
4529 | | bytes32 m3;
4530 | | bytes32 m4;
4531 | | /// @solidity memory-safe-assembly
4532 | | assembly {
4533 | | m0 := mload(0x00)
4534 | | m1 := mload(0x20)
4535 | | m2 := mload(0x40)
4536 | | m3 := mload(0x60)
4537 | | m4 := mload(0x80)
4538 | | // Selector of `log(address,uint256,uint256,uint256)`.
4539 | | mstore(0x00, 0x34f0e636)
4540 | | mstore(0x20, p0)
4541 | | mstore(0x40, p1)
4542 | | mstore(0x60, p2)
4543 | | mstore(0x80, p3)
4544 | | }
4545 | | _sendLogPayload(0x1c, 0x84);
4546 | | /// @solidity memory-safe-assembly
4547 | | assembly {
4548 | | mstore(0x00, m0)
4549 | | mstore(0x20, m1)
4550 | | mstore(0x40, m2)
4551 | | mstore(0x60, m3)
4552 | | mstore(0x80, m4)
4553 | | }
4554 | | }
4555 | |
4556 | | function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
4557 | | bytes32 m0;
4558 | | bytes32 m1;
4559 | | bytes32 m2;
4560 | | bytes32 m3;
4561 | | bytes32 m4;
4562 | | bytes32 m5;
4563 | | bytes32 m6;
4564 | | /// @solidity memory-safe-assembly
4565 | | assembly {
4566 | | function writeString(pos, w) {
4567 | | let length := 0
4568 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4569 | | mstore(pos, length)
4570 | | let shift := sub(256, shl(3, length))
4571 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4572 | | }
4573 | | m0 := mload(0x00)
4574 | | m1 := mload(0x20)
4575 | | m2 := mload(0x40)
4576 | | m3 := mload(0x60)
4577 | | m4 := mload(0x80)
4578 | | m5 := mload(0xa0)
4579 | | m6 := mload(0xc0)
4580 | | // Selector of `log(address,uint256,uint256,string)`.
4581 | | mstore(0x00, 0x4a28c017)
4582 | | mstore(0x20, p0)
4583 | | mstore(0x40, p1)
4584 | | mstore(0x60, p2)
4585 | | mstore(0x80, 0x80)
4586 | | writeString(0xa0, p3)
4587 | | }
4588 | | _sendLogPayload(0x1c, 0xc4);
4589 | | /// @solidity memory-safe-assembly
4590 | | assembly {
4591 | | mstore(0x00, m0)
4592 | | mstore(0x20, m1)
4593 | | mstore(0x40, m2)
4594 | | mstore(0x60, m3)
4595 | | mstore(0x80, m4)
4596 | | mstore(0xa0, m5)
4597 | | mstore(0xc0, m6)
4598 | | }
4599 | | }
4600 | |
4601 | | function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure {
4602 | | bytes32 m0;
4603 | | bytes32 m1;
4604 | | bytes32 m2;
4605 | | bytes32 m3;
4606 | | bytes32 m4;
4607 | | bytes32 m5;
4608 | | bytes32 m6;
4609 | | /// @solidity memory-safe-assembly
4610 | | assembly {
4611 | | function writeString(pos, w) {
4612 | | let length := 0
4613 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4614 | | mstore(pos, length)
4615 | | let shift := sub(256, shl(3, length))
4616 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4617 | | }
4618 | | m0 := mload(0x00)
4619 | | m1 := mload(0x20)
4620 | | m2 := mload(0x40)
4621 | | m3 := mload(0x60)
4622 | | m4 := mload(0x80)
4623 | | m5 := mload(0xa0)
4624 | | m6 := mload(0xc0)
4625 | | // Selector of `log(address,uint256,string,address)`.
4626 | | mstore(0x00, 0x5c430d47)
4627 | | mstore(0x20, p0)
4628 | | mstore(0x40, p1)
4629 | | mstore(0x60, 0x80)
4630 | | mstore(0x80, p3)
4631 | | writeString(0xa0, p2)
4632 | | }
4633 | | _sendLogPayload(0x1c, 0xc4);
4634 | | /// @solidity memory-safe-assembly
4635 | | assembly {
4636 | | mstore(0x00, m0)
4637 | | mstore(0x20, m1)
4638 | | mstore(0x40, m2)
4639 | | mstore(0x60, m3)
4640 | | mstore(0x80, m4)
4641 | | mstore(0xa0, m5)
4642 | | mstore(0xc0, m6)
4643 | | }
4644 | | }
4645 | |
4646 | | function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure {
4647 | | bytes32 m0;
4648 | | bytes32 m1;
4649 | | bytes32 m2;
4650 | | bytes32 m3;
4651 | | bytes32 m4;
4652 | | bytes32 m5;
4653 | | bytes32 m6;
4654 | | /// @solidity memory-safe-assembly
4655 | | assembly {
4656 | | function writeString(pos, w) {
4657 | | let length := 0
4658 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4659 | | mstore(pos, length)
4660 | | let shift := sub(256, shl(3, length))
4661 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4662 | | }
4663 | | m0 := mload(0x00)
4664 | | m1 := mload(0x20)
4665 | | m2 := mload(0x40)
4666 | | m3 := mload(0x60)
4667 | | m4 := mload(0x80)
4668 | | m5 := mload(0xa0)
4669 | | m6 := mload(0xc0)
4670 | | // Selector of `log(address,uint256,string,bool)`.
4671 | | mstore(0x00, 0xcf18105c)
4672 | | mstore(0x20, p0)
4673 | | mstore(0x40, p1)
4674 | | mstore(0x60, 0x80)
4675 | | mstore(0x80, p3)
4676 | | writeString(0xa0, p2)
4677 | | }
4678 | | _sendLogPayload(0x1c, 0xc4);
4679 | | /// @solidity memory-safe-assembly
4680 | | assembly {
4681 | | mstore(0x00, m0)
4682 | | mstore(0x20, m1)
4683 | | mstore(0x40, m2)
4684 | | mstore(0x60, m3)
4685 | | mstore(0x80, m4)
4686 | | mstore(0xa0, m5)
4687 | | mstore(0xc0, m6)
4688 | | }
4689 | | }
4690 | |
4691 | | function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
4692 | | bytes32 m0;
4693 | | bytes32 m1;
4694 | | bytes32 m2;
4695 | | bytes32 m3;
4696 | | bytes32 m4;
4697 | | bytes32 m5;
4698 | | bytes32 m6;
4699 | | /// @solidity memory-safe-assembly
4700 | | assembly {
4701 | | function writeString(pos, w) {
4702 | | let length := 0
4703 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4704 | | mstore(pos, length)
4705 | | let shift := sub(256, shl(3, length))
4706 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4707 | | }
4708 | | m0 := mload(0x00)
4709 | | m1 := mload(0x20)
4710 | | m2 := mload(0x40)
4711 | | m3 := mload(0x60)
4712 | | m4 := mload(0x80)
4713 | | m5 := mload(0xa0)
4714 | | m6 := mload(0xc0)
4715 | | // Selector of `log(address,uint256,string,uint256)`.
4716 | | mstore(0x00, 0xbf01f891)
4717 | | mstore(0x20, p0)
4718 | | mstore(0x40, p1)
4719 | | mstore(0x60, 0x80)
4720 | | mstore(0x80, p3)
4721 | | writeString(0xa0, p2)
4722 | | }
4723 | | _sendLogPayload(0x1c, 0xc4);
4724 | | /// @solidity memory-safe-assembly
4725 | | assembly {
4726 | | mstore(0x00, m0)
4727 | | mstore(0x20, m1)
4728 | | mstore(0x40, m2)
4729 | | mstore(0x60, m3)
4730 | | mstore(0x80, m4)
4731 | | mstore(0xa0, m5)
4732 | | mstore(0xc0, m6)
4733 | | }
4734 | | }
4735 | |
4736 | | function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
4737 | | bytes32 m0;
4738 | | bytes32 m1;
4739 | | bytes32 m2;
4740 | | bytes32 m3;
4741 | | bytes32 m4;
4742 | | bytes32 m5;
4743 | | bytes32 m6;
4744 | | bytes32 m7;
4745 | | bytes32 m8;
4746 | | /// @solidity memory-safe-assembly
4747 | | assembly {
4748 | | function writeString(pos, w) {
4749 | | let length := 0
4750 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4751 | | mstore(pos, length)
4752 | | let shift := sub(256, shl(3, length))
4753 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4754 | | }
4755 | | m0 := mload(0x00)
4756 | | m1 := mload(0x20)
4757 | | m2 := mload(0x40)
4758 | | m3 := mload(0x60)
4759 | | m4 := mload(0x80)
4760 | | m5 := mload(0xa0)
4761 | | m6 := mload(0xc0)
4762 | | m7 := mload(0xe0)
4763 | | m8 := mload(0x100)
4764 | | // Selector of `log(address,uint256,string,string)`.
4765 | | mstore(0x00, 0x88a8c406)
4766 | | mstore(0x20, p0)
4767 | | mstore(0x40, p1)
4768 | | mstore(0x60, 0x80)
4769 | | mstore(0x80, 0xc0)
4770 | | writeString(0xa0, p2)
4771 | | writeString(0xe0, p3)
4772 | | }
4773 | | _sendLogPayload(0x1c, 0x104);
4774 | | /// @solidity memory-safe-assembly
4775 | | assembly {
4776 | | mstore(0x00, m0)
4777 | | mstore(0x20, m1)
4778 | | mstore(0x40, m2)
4779 | | mstore(0x60, m3)
4780 | | mstore(0x80, m4)
4781 | | mstore(0xa0, m5)
4782 | | mstore(0xc0, m6)
4783 | | mstore(0xe0, m7)
4784 | | mstore(0x100, m8)
4785 | | }
4786 | | }
4787 | |
4788 | | function log(address p0, bytes32 p1, address p2, address p3) internal pure {
4789 | | bytes32 m0;
4790 | | bytes32 m1;
4791 | | bytes32 m2;
4792 | | bytes32 m3;
4793 | | bytes32 m4;
4794 | | bytes32 m5;
4795 | | bytes32 m6;
4796 | | /// @solidity memory-safe-assembly
4797 | | assembly {
4798 | | function writeString(pos, w) {
4799 | | let length := 0
4800 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4801 | | mstore(pos, length)
4802 | | let shift := sub(256, shl(3, length))
4803 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4804 | | }
4805 | | m0 := mload(0x00)
4806 | | m1 := mload(0x20)
4807 | | m2 := mload(0x40)
4808 | | m3 := mload(0x60)
4809 | | m4 := mload(0x80)
4810 | | m5 := mload(0xa0)
4811 | | m6 := mload(0xc0)
4812 | | // Selector of `log(address,string,address,address)`.
4813 | | mstore(0x00, 0x0d36fa20)
4814 | | mstore(0x20, p0)
4815 | | mstore(0x40, 0x80)
4816 | | mstore(0x60, p2)
4817 | | mstore(0x80, p3)
4818 | | writeString(0xa0, p1)
4819 | | }
4820 | | _sendLogPayload(0x1c, 0xc4);
4821 | | /// @solidity memory-safe-assembly
4822 | | assembly {
4823 | | mstore(0x00, m0)
4824 | | mstore(0x20, m1)
4825 | | mstore(0x40, m2)
4826 | | mstore(0x60, m3)
4827 | | mstore(0x80, m4)
4828 | | mstore(0xa0, m5)
4829 | | mstore(0xc0, m6)
4830 | | }
4831 | | }
4832 | |
4833 | | function log(address p0, bytes32 p1, address p2, bool p3) internal pure {
4834 | | bytes32 m0;
4835 | | bytes32 m1;
4836 | | bytes32 m2;
4837 | | bytes32 m3;
4838 | | bytes32 m4;
4839 | | bytes32 m5;
4840 | | bytes32 m6;
4841 | | /// @solidity memory-safe-assembly
4842 | | assembly {
4843 | | function writeString(pos, w) {
4844 | | let length := 0
4845 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4846 | | mstore(pos, length)
4847 | | let shift := sub(256, shl(3, length))
4848 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4849 | | }
4850 | | m0 := mload(0x00)
4851 | | m1 := mload(0x20)
4852 | | m2 := mload(0x40)
4853 | | m3 := mload(0x60)
4854 | | m4 := mload(0x80)
4855 | | m5 := mload(0xa0)
4856 | | m6 := mload(0xc0)
4857 | | // Selector of `log(address,string,address,bool)`.
4858 | | mstore(0x00, 0x0df12b76)
4859 | | mstore(0x20, p0)
4860 | | mstore(0x40, 0x80)
4861 | | mstore(0x60, p2)
4862 | | mstore(0x80, p3)
4863 | | writeString(0xa0, p1)
4864 | | }
4865 | | _sendLogPayload(0x1c, 0xc4);
4866 | | /// @solidity memory-safe-assembly
4867 | | assembly {
4868 | | mstore(0x00, m0)
4869 | | mstore(0x20, m1)
4870 | | mstore(0x40, m2)
4871 | | mstore(0x60, m3)
4872 | | mstore(0x80, m4)
4873 | | mstore(0xa0, m5)
4874 | | mstore(0xc0, m6)
4875 | | }
4876 | | }
4877 | |
4878 | | function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure {
4879 | | bytes32 m0;
4880 | | bytes32 m1;
4881 | | bytes32 m2;
4882 | | bytes32 m3;
4883 | | bytes32 m4;
4884 | | bytes32 m5;
4885 | | bytes32 m6;
4886 | | /// @solidity memory-safe-assembly
4887 | | assembly {
4888 | | function writeString(pos, w) {
4889 | | let length := 0
4890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4891 | | mstore(pos, length)
4892 | | let shift := sub(256, shl(3, length))
4893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4894 | | }
4895 | | m0 := mload(0x00)
4896 | | m1 := mload(0x20)
4897 | | m2 := mload(0x40)
4898 | | m3 := mload(0x60)
4899 | | m4 := mload(0x80)
4900 | | m5 := mload(0xa0)
4901 | | m6 := mload(0xc0)
4902 | | // Selector of `log(address,string,address,uint256)`.
4903 | | mstore(0x00, 0x457fe3cf)
4904 | | mstore(0x20, p0)
4905 | | mstore(0x40, 0x80)
4906 | | mstore(0x60, p2)
4907 | | mstore(0x80, p3)
4908 | | writeString(0xa0, p1)
4909 | | }
4910 | | _sendLogPayload(0x1c, 0xc4);
4911 | | /// @solidity memory-safe-assembly
4912 | | assembly {
4913 | | mstore(0x00, m0)
4914 | | mstore(0x20, m1)
4915 | | mstore(0x40, m2)
4916 | | mstore(0x60, m3)
4917 | | mstore(0x80, m4)
4918 | | mstore(0xa0, m5)
4919 | | mstore(0xc0, m6)
4920 | | }
4921 | | }
4922 | |
4923 | | function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure {
4924 | | bytes32 m0;
4925 | | bytes32 m1;
4926 | | bytes32 m2;
4927 | | bytes32 m3;
4928 | | bytes32 m4;
4929 | | bytes32 m5;
4930 | | bytes32 m6;
4931 | | bytes32 m7;
4932 | | bytes32 m8;
4933 | | /// @solidity memory-safe-assembly
4934 | | assembly {
4935 | | function writeString(pos, w) {
4936 | | let length := 0
4937 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4938 | | mstore(pos, length)
4939 | | let shift := sub(256, shl(3, length))
4940 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4941 | | }
4942 | | m0 := mload(0x00)
4943 | | m1 := mload(0x20)
4944 | | m2 := mload(0x40)
4945 | | m3 := mload(0x60)
4946 | | m4 := mload(0x80)
4947 | | m5 := mload(0xa0)
4948 | | m6 := mload(0xc0)
4949 | | m7 := mload(0xe0)
4950 | | m8 := mload(0x100)
4951 | | // Selector of `log(address,string,address,string)`.
4952 | | mstore(0x00, 0xf7e36245)
4953 | | mstore(0x20, p0)
4954 | | mstore(0x40, 0x80)
4955 | | mstore(0x60, p2)
4956 | | mstore(0x80, 0xc0)
4957 | | writeString(0xa0, p1)
4958 | | writeString(0xe0, p3)
4959 | | }
4960 | | _sendLogPayload(0x1c, 0x104);
4961 | | /// @solidity memory-safe-assembly
4962 | | assembly {
4963 | | mstore(0x00, m0)
4964 | | mstore(0x20, m1)
4965 | | mstore(0x40, m2)
4966 | | mstore(0x60, m3)
4967 | | mstore(0x80, m4)
4968 | | mstore(0xa0, m5)
4969 | | mstore(0xc0, m6)
4970 | | mstore(0xe0, m7)
4971 | | mstore(0x100, m8)
4972 | | }
4973 | | }
4974 | |
4975 | | function log(address p0, bytes32 p1, bool p2, address p3) internal pure {
4976 | | bytes32 m0;
4977 | | bytes32 m1;
4978 | | bytes32 m2;
4979 | | bytes32 m3;
4980 | | bytes32 m4;
4981 | | bytes32 m5;
4982 | | bytes32 m6;
4983 | | /// @solidity memory-safe-assembly
4984 | | assembly {
4985 | | function writeString(pos, w) {
4986 | | let length := 0
4987 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4988 | | mstore(pos, length)
4989 | | let shift := sub(256, shl(3, length))
4990 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4991 | | }
4992 | | m0 := mload(0x00)
4993 | | m1 := mload(0x20)
4994 | | m2 := mload(0x40)
4995 | | m3 := mload(0x60)
4996 | | m4 := mload(0x80)
4997 | | m5 := mload(0xa0)
4998 | | m6 := mload(0xc0)
4999 | | // Selector of `log(address,string,bool,address)`.
5000 | | mstore(0x00, 0x205871c2)
5001 | | mstore(0x20, p0)
5002 | | mstore(0x40, 0x80)
5003 | | mstore(0x60, p2)
5004 | | mstore(0x80, p3)
5005 | | writeString(0xa0, p1)
5006 | | }
5007 | | _sendLogPayload(0x1c, 0xc4);
5008 | | /// @solidity memory-safe-assembly
5009 | | assembly {
5010 | | mstore(0x00, m0)
5011 | | mstore(0x20, m1)
5012 | | mstore(0x40, m2)
5013 | | mstore(0x60, m3)
5014 | | mstore(0x80, m4)
5015 | | mstore(0xa0, m5)
5016 | | mstore(0xc0, m6)
5017 | | }
5018 | | }
5019 | |
5020 | | function log(address p0, bytes32 p1, bool p2, bool p3) internal pure {
5021 | | bytes32 m0;
5022 | | bytes32 m1;
5023 | | bytes32 m2;
5024 | | bytes32 m3;
5025 | | bytes32 m4;
5026 | | bytes32 m5;
5027 | | bytes32 m6;
5028 | | /// @solidity memory-safe-assembly
5029 | | assembly {
5030 | | function writeString(pos, w) {
5031 | | let length := 0
5032 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5033 | | mstore(pos, length)
5034 | | let shift := sub(256, shl(3, length))
5035 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5036 | | }
5037 | | m0 := mload(0x00)
5038 | | m1 := mload(0x20)
5039 | | m2 := mload(0x40)
5040 | | m3 := mload(0x60)
5041 | | m4 := mload(0x80)
5042 | | m5 := mload(0xa0)
5043 | | m6 := mload(0xc0)
5044 | | // Selector of `log(address,string,bool,bool)`.
5045 | | mstore(0x00, 0x5f1d5c9f)
5046 | | mstore(0x20, p0)
5047 | | mstore(0x40, 0x80)
5048 | | mstore(0x60, p2)
5049 | | mstore(0x80, p3)
5050 | | writeString(0xa0, p1)
5051 | | }
5052 | | _sendLogPayload(0x1c, 0xc4);
5053 | | /// @solidity memory-safe-assembly
5054 | | assembly {
5055 | | mstore(0x00, m0)
5056 | | mstore(0x20, m1)
5057 | | mstore(0x40, m2)
5058 | | mstore(0x60, m3)
5059 | | mstore(0x80, m4)
5060 | | mstore(0xa0, m5)
5061 | | mstore(0xc0, m6)
5062 | | }
5063 | | }
5064 | |
5065 | | function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure {
5066 | | bytes32 m0;
5067 | | bytes32 m1;
5068 | | bytes32 m2;
5069 | | bytes32 m3;
5070 | | bytes32 m4;
5071 | | bytes32 m5;
5072 | | bytes32 m6;
5073 | | /// @solidity memory-safe-assembly
5074 | | assembly {
5075 | | function writeString(pos, w) {
5076 | | let length := 0
5077 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5078 | | mstore(pos, length)
5079 | | let shift := sub(256, shl(3, length))
5080 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5081 | | }
5082 | | m0 := mload(0x00)
5083 | | m1 := mload(0x20)
5084 | | m2 := mload(0x40)
5085 | | m3 := mload(0x60)
5086 | | m4 := mload(0x80)
5087 | | m5 := mload(0xa0)
5088 | | m6 := mload(0xc0)
5089 | | // Selector of `log(address,string,bool,uint256)`.
5090 | | mstore(0x00, 0x515e38b6)
5091 | | mstore(0x20, p0)
5092 | | mstore(0x40, 0x80)
5093 | | mstore(0x60, p2)
5094 | | mstore(0x80, p3)
5095 | | writeString(0xa0, p1)
5096 | | }
5097 | | _sendLogPayload(0x1c, 0xc4);
5098 | | /// @solidity memory-safe-assembly
5099 | | assembly {
5100 | | mstore(0x00, m0)
5101 | | mstore(0x20, m1)
5102 | | mstore(0x40, m2)
5103 | | mstore(0x60, m3)
5104 | | mstore(0x80, m4)
5105 | | mstore(0xa0, m5)
5106 | | mstore(0xc0, m6)
5107 | | }
5108 | | }
5109 | |
5110 | | function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
5111 | | bytes32 m0;
5112 | | bytes32 m1;
5113 | | bytes32 m2;
5114 | | bytes32 m3;
5115 | | bytes32 m4;
5116 | | bytes32 m5;
5117 | | bytes32 m6;
5118 | | bytes32 m7;
5119 | | bytes32 m8;
5120 | | /// @solidity memory-safe-assembly
5121 | | assembly {
5122 | | function writeString(pos, w) {
5123 | | let length := 0
5124 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5125 | | mstore(pos, length)
5126 | | let shift := sub(256, shl(3, length))
5127 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5128 | | }
5129 | | m0 := mload(0x00)
5130 | | m1 := mload(0x20)
5131 | | m2 := mload(0x40)
5132 | | m3 := mload(0x60)
5133 | | m4 := mload(0x80)
5134 | | m5 := mload(0xa0)
5135 | | m6 := mload(0xc0)
5136 | | m7 := mload(0xe0)
5137 | | m8 := mload(0x100)
5138 | | // Selector of `log(address,string,bool,string)`.
5139 | | mstore(0x00, 0xbc0b61fe)
5140 | | mstore(0x20, p0)
5141 | | mstore(0x40, 0x80)
5142 | | mstore(0x60, p2)
5143 | | mstore(0x80, 0xc0)
5144 | | writeString(0xa0, p1)
5145 | | writeString(0xe0, p3)
5146 | | }
5147 | | _sendLogPayload(0x1c, 0x104);
5148 | | /// @solidity memory-safe-assembly
5149 | | assembly {
5150 | | mstore(0x00, m0)
5151 | | mstore(0x20, m1)
5152 | | mstore(0x40, m2)
5153 | | mstore(0x60, m3)
5154 | | mstore(0x80, m4)
5155 | | mstore(0xa0, m5)
5156 | | mstore(0xc0, m6)
5157 | | mstore(0xe0, m7)
5158 | | mstore(0x100, m8)
5159 | | }
5160 | | }
5161 | |
5162 | | function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure {
5163 | | bytes32 m0;
5164 | | bytes32 m1;
5165 | | bytes32 m2;
5166 | | bytes32 m3;
5167 | | bytes32 m4;
5168 | | bytes32 m5;
5169 | | bytes32 m6;
5170 | | /// @solidity memory-safe-assembly
5171 | | assembly {
5172 | | function writeString(pos, w) {
5173 | | let length := 0
5174 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5175 | | mstore(pos, length)
5176 | | let shift := sub(256, shl(3, length))
5177 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5178 | | }
5179 | | m0 := mload(0x00)
5180 | | m1 := mload(0x20)
5181 | | m2 := mload(0x40)
5182 | | m3 := mload(0x60)
5183 | | m4 := mload(0x80)
5184 | | m5 := mload(0xa0)
5185 | | m6 := mload(0xc0)
5186 | | // Selector of `log(address,string,uint256,address)`.
5187 | | mstore(0x00, 0x63183678)
5188 | | mstore(0x20, p0)
5189 | | mstore(0x40, 0x80)
5190 | | mstore(0x60, p2)
5191 | | mstore(0x80, p3)
5192 | | writeString(0xa0, p1)
5193 | | }
5194 | | _sendLogPayload(0x1c, 0xc4);
5195 | | /// @solidity memory-safe-assembly
5196 | | assembly {
5197 | | mstore(0x00, m0)
5198 | | mstore(0x20, m1)
5199 | | mstore(0x40, m2)
5200 | | mstore(0x60, m3)
5201 | | mstore(0x80, m4)
5202 | | mstore(0xa0, m5)
5203 | | mstore(0xc0, m6)
5204 | | }
5205 | | }
5206 | |
5207 | | function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure {
5208 | | bytes32 m0;
5209 | | bytes32 m1;
5210 | | bytes32 m2;
5211 | | bytes32 m3;
5212 | | bytes32 m4;
5213 | | bytes32 m5;
5214 | | bytes32 m6;
5215 | | /// @solidity memory-safe-assembly
5216 | | assembly {
5217 | | function writeString(pos, w) {
5218 | | let length := 0
5219 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5220 | | mstore(pos, length)
5221 | | let shift := sub(256, shl(3, length))
5222 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5223 | | }
5224 | | m0 := mload(0x00)
5225 | | m1 := mload(0x20)
5226 | | m2 := mload(0x40)
5227 | | m3 := mload(0x60)
5228 | | m4 := mload(0x80)
5229 | | m5 := mload(0xa0)
5230 | | m6 := mload(0xc0)
5231 | | // Selector of `log(address,string,uint256,bool)`.
5232 | | mstore(0x00, 0x0ef7e050)
5233 | | mstore(0x20, p0)
5234 | | mstore(0x40, 0x80)
5235 | | mstore(0x60, p2)
5236 | | mstore(0x80, p3)
5237 | | writeString(0xa0, p1)
5238 | | }
5239 | | _sendLogPayload(0x1c, 0xc4);
5240 | | /// @solidity memory-safe-assembly
5241 | | assembly {
5242 | | mstore(0x00, m0)
5243 | | mstore(0x20, m1)
5244 | | mstore(0x40, m2)
5245 | | mstore(0x60, m3)
5246 | | mstore(0x80, m4)
5247 | | mstore(0xa0, m5)
5248 | | mstore(0xc0, m6)
5249 | | }
5250 | | }
5251 | |
5252 | | function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
5253 | | bytes32 m0;
5254 | | bytes32 m1;
5255 | | bytes32 m2;
5256 | | bytes32 m3;
5257 | | bytes32 m4;
5258 | | bytes32 m5;
5259 | | bytes32 m6;
5260 | | /// @solidity memory-safe-assembly
5261 | | assembly {
5262 | | function writeString(pos, w) {
5263 | | let length := 0
5264 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5265 | | mstore(pos, length)
5266 | | let shift := sub(256, shl(3, length))
5267 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5268 | | }
5269 | | m0 := mload(0x00)
5270 | | m1 := mload(0x20)
5271 | | m2 := mload(0x40)
5272 | | m3 := mload(0x60)
5273 | | m4 := mload(0x80)
5274 | | m5 := mload(0xa0)
5275 | | m6 := mload(0xc0)
5276 | | // Selector of `log(address,string,uint256,uint256)`.
5277 | | mstore(0x00, 0x1dc8e1b8)
5278 | | mstore(0x20, p0)
5279 | | mstore(0x40, 0x80)
5280 | | mstore(0x60, p2)
5281 | | mstore(0x80, p3)
5282 | | writeString(0xa0, p1)
5283 | | }
5284 | | _sendLogPayload(0x1c, 0xc4);
5285 | | /// @solidity memory-safe-assembly
5286 | | assembly {
5287 | | mstore(0x00, m0)
5288 | | mstore(0x20, m1)
5289 | | mstore(0x40, m2)
5290 | | mstore(0x60, m3)
5291 | | mstore(0x80, m4)
5292 | | mstore(0xa0, m5)
5293 | | mstore(0xc0, m6)
5294 | | }
5295 | | }
5296 | |
5297 | | function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
5298 | | bytes32 m0;
5299 | | bytes32 m1;
5300 | | bytes32 m2;
5301 | | bytes32 m3;
5302 | | bytes32 m4;
5303 | | bytes32 m5;
5304 | | bytes32 m6;
5305 | | bytes32 m7;
5306 | | bytes32 m8;
5307 | | /// @solidity memory-safe-assembly
5308 | | assembly {
5309 | | function writeString(pos, w) {
5310 | | let length := 0
5311 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5312 | | mstore(pos, length)
5313 | | let shift := sub(256, shl(3, length))
5314 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5315 | | }
5316 | | m0 := mload(0x00)
5317 | | m1 := mload(0x20)
5318 | | m2 := mload(0x40)
5319 | | m3 := mload(0x60)
5320 | | m4 := mload(0x80)
5321 | | m5 := mload(0xa0)
5322 | | m6 := mload(0xc0)
5323 | | m7 := mload(0xe0)
5324 | | m8 := mload(0x100)
5325 | | // Selector of `log(address,string,uint256,string)`.
5326 | | mstore(0x00, 0x448830a8)
5327 | | mstore(0x20, p0)
5328 | | mstore(0x40, 0x80)
5329 | | mstore(0x60, p2)
5330 | | mstore(0x80, 0xc0)
5331 | | writeString(0xa0, p1)
5332 | | writeString(0xe0, p3)
5333 | | }
5334 | | _sendLogPayload(0x1c, 0x104);
5335 | | /// @solidity memory-safe-assembly
5336 | | assembly {
5337 | | mstore(0x00, m0)
5338 | | mstore(0x20, m1)
5339 | | mstore(0x40, m2)
5340 | | mstore(0x60, m3)
5341 | | mstore(0x80, m4)
5342 | | mstore(0xa0, m5)
5343 | | mstore(0xc0, m6)
5344 | | mstore(0xe0, m7)
5345 | | mstore(0x100, m8)
5346 | | }
5347 | | }
5348 | |
5349 | | function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure {
5350 | | bytes32 m0;
5351 | | bytes32 m1;
5352 | | bytes32 m2;
5353 | | bytes32 m3;
5354 | | bytes32 m4;
5355 | | bytes32 m5;
5356 | | bytes32 m6;
5357 | | bytes32 m7;
5358 | | bytes32 m8;
5359 | | /// @solidity memory-safe-assembly
5360 | | assembly {
5361 | | function writeString(pos, w) {
5362 | | let length := 0
5363 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5364 | | mstore(pos, length)
5365 | | let shift := sub(256, shl(3, length))
5366 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5367 | | }
5368 | | m0 := mload(0x00)
5369 | | m1 := mload(0x20)
5370 | | m2 := mload(0x40)
5371 | | m3 := mload(0x60)
5372 | | m4 := mload(0x80)
5373 | | m5 := mload(0xa0)
5374 | | m6 := mload(0xc0)
5375 | | m7 := mload(0xe0)
5376 | | m8 := mload(0x100)
5377 | | // Selector of `log(address,string,string,address)`.
5378 | | mstore(0x00, 0xa04e2f87)
5379 | | mstore(0x20, p0)
5380 | | mstore(0x40, 0x80)
5381 | | mstore(0x60, 0xc0)
5382 | | mstore(0x80, p3)
5383 | | writeString(0xa0, p1)
5384 | | writeString(0xe0, p2)
5385 | | }
5386 | | _sendLogPayload(0x1c, 0x104);
5387 | | /// @solidity memory-safe-assembly
5388 | | assembly {
5389 | | mstore(0x00, m0)
5390 | | mstore(0x20, m1)
5391 | | mstore(0x40, m2)
5392 | | mstore(0x60, m3)
5393 | | mstore(0x80, m4)
5394 | | mstore(0xa0, m5)
5395 | | mstore(0xc0, m6)
5396 | | mstore(0xe0, m7)
5397 | | mstore(0x100, m8)
5398 | | }
5399 | | }
5400 | |
5401 | | function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
5402 | | bytes32 m0;
5403 | | bytes32 m1;
5404 | | bytes32 m2;
5405 | | bytes32 m3;
5406 | | bytes32 m4;
5407 | | bytes32 m5;
5408 | | bytes32 m6;
5409 | | bytes32 m7;
5410 | | bytes32 m8;
5411 | | /// @solidity memory-safe-assembly
5412 | | assembly {
5413 | | function writeString(pos, w) {
5414 | | let length := 0
5415 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5416 | | mstore(pos, length)
5417 | | let shift := sub(256, shl(3, length))
5418 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5419 | | }
5420 | | m0 := mload(0x00)
5421 | | m1 := mload(0x20)
5422 | | m2 := mload(0x40)
5423 | | m3 := mload(0x60)
5424 | | m4 := mload(0x80)
5425 | | m5 := mload(0xa0)
5426 | | m6 := mload(0xc0)
5427 | | m7 := mload(0xe0)
5428 | | m8 := mload(0x100)
5429 | | // Selector of `log(address,string,string,bool)`.
5430 | | mstore(0x00, 0x35a5071f)
5431 | | mstore(0x20, p0)
5432 | | mstore(0x40, 0x80)
5433 | | mstore(0x60, 0xc0)
5434 | | mstore(0x80, p3)
5435 | | writeString(0xa0, p1)
5436 | | writeString(0xe0, p2)
5437 | | }
5438 | | _sendLogPayload(0x1c, 0x104);
5439 | | /// @solidity memory-safe-assembly
5440 | | assembly {
5441 | | mstore(0x00, m0)
5442 | | mstore(0x20, m1)
5443 | | mstore(0x40, m2)
5444 | | mstore(0x60, m3)
5445 | | mstore(0x80, m4)
5446 | | mstore(0xa0, m5)
5447 | | mstore(0xc0, m6)
5448 | | mstore(0xe0, m7)
5449 | | mstore(0x100, m8)
5450 | | }
5451 | | }
5452 | |
5453 | | function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
5454 | | bytes32 m0;
5455 | | bytes32 m1;
5456 | | bytes32 m2;
5457 | | bytes32 m3;
5458 | | bytes32 m4;
5459 | | bytes32 m5;
5460 | | bytes32 m6;
5461 | | bytes32 m7;
5462 | | bytes32 m8;
5463 | | /// @solidity memory-safe-assembly
5464 | | assembly {
5465 | | function writeString(pos, w) {
5466 | | let length := 0
5467 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5468 | | mstore(pos, length)
5469 | | let shift := sub(256, shl(3, length))
5470 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5471 | | }
5472 | | m0 := mload(0x00)
5473 | | m1 := mload(0x20)
5474 | | m2 := mload(0x40)
5475 | | m3 := mload(0x60)
5476 | | m4 := mload(0x80)
5477 | | m5 := mload(0xa0)
5478 | | m6 := mload(0xc0)
5479 | | m7 := mload(0xe0)
5480 | | m8 := mload(0x100)
5481 | | // Selector of `log(address,string,string,uint256)`.
5482 | | mstore(0x00, 0x159f8927)
5483 | | mstore(0x20, p0)
5484 | | mstore(0x40, 0x80)
5485 | | mstore(0x60, 0xc0)
5486 | | mstore(0x80, p3)
5487 | | writeString(0xa0, p1)
5488 | | writeString(0xe0, p2)
5489 | | }
5490 | | _sendLogPayload(0x1c, 0x104);
5491 | | /// @solidity memory-safe-assembly
5492 | | assembly {
5493 | | mstore(0x00, m0)
5494 | | mstore(0x20, m1)
5495 | | mstore(0x40, m2)
5496 | | mstore(0x60, m3)
5497 | | mstore(0x80, m4)
5498 | | mstore(0xa0, m5)
5499 | | mstore(0xc0, m6)
5500 | | mstore(0xe0, m7)
5501 | | mstore(0x100, m8)
5502 | | }
5503 | | }
5504 | |
5505 | | function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
5506 | | bytes32 m0;
5507 | | bytes32 m1;
5508 | | bytes32 m2;
5509 | | bytes32 m3;
5510 | | bytes32 m4;
5511 | | bytes32 m5;
5512 | | bytes32 m6;
5513 | | bytes32 m7;
5514 | | bytes32 m8;
5515 | | bytes32 m9;
5516 | | bytes32 m10;
5517 | | /// @solidity memory-safe-assembly
5518 | | assembly {
5519 | | function writeString(pos, w) {
5520 | | let length := 0
5521 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5522 | | mstore(pos, length)
5523 | | let shift := sub(256, shl(3, length))
5524 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5525 | | }
5526 | | m0 := mload(0x00)
5527 | | m1 := mload(0x20)
5528 | | m2 := mload(0x40)
5529 | | m3 := mload(0x60)
5530 | | m4 := mload(0x80)
5531 | | m5 := mload(0xa0)
5532 | | m6 := mload(0xc0)
5533 | | m7 := mload(0xe0)
5534 | | m8 := mload(0x100)
5535 | | m9 := mload(0x120)
5536 | | m10 := mload(0x140)
5537 | | // Selector of `log(address,string,string,string)`.
5538 | | mstore(0x00, 0x5d02c50b)
5539 | | mstore(0x20, p0)
5540 | | mstore(0x40, 0x80)
5541 | | mstore(0x60, 0xc0)
5542 | | mstore(0x80, 0x100)
5543 | | writeString(0xa0, p1)
5544 | | writeString(0xe0, p2)
5545 | | writeString(0x120, p3)
5546 | | }
5547 | | _sendLogPayload(0x1c, 0x144);
5548 | | /// @solidity memory-safe-assembly
5549 | | assembly {
5550 | | mstore(0x00, m0)
5551 | | mstore(0x20, m1)
5552 | | mstore(0x40, m2)
5553 | | mstore(0x60, m3)
5554 | | mstore(0x80, m4)
5555 | | mstore(0xa0, m5)
5556 | | mstore(0xc0, m6)
5557 | | mstore(0xe0, m7)
5558 | | mstore(0x100, m8)
5559 | | mstore(0x120, m9)
5560 | | mstore(0x140, m10)
5561 | | }
5562 | | }
5563 | |
5564 | | function log(bool p0, address p1, address p2, address p3) internal pure {
5565 | | bytes32 m0;
5566 | | bytes32 m1;
5567 | | bytes32 m2;
5568 | | bytes32 m3;
5569 | | bytes32 m4;
5570 | | /// @solidity memory-safe-assembly
5571 | | assembly {
5572 | | m0 := mload(0x00)
5573 | | m1 := mload(0x20)
5574 | | m2 := mload(0x40)
5575 | | m3 := mload(0x60)
5576 | | m4 := mload(0x80)
5577 | | // Selector of `log(bool,address,address,address)`.
5578 | | mstore(0x00, 0x1d14d001)
5579 | | mstore(0x20, p0)
5580 | | mstore(0x40, p1)
5581 | | mstore(0x60, p2)
5582 | | mstore(0x80, p3)
5583 | | }
5584 | | _sendLogPayload(0x1c, 0x84);
5585 | | /// @solidity memory-safe-assembly
5586 | | assembly {
5587 | | mstore(0x00, m0)
5588 | | mstore(0x20, m1)
5589 | | mstore(0x40, m2)
5590 | | mstore(0x60, m3)
5591 | | mstore(0x80, m4)
5592 | | }
5593 | | }
5594 | |
5595 | | function log(bool p0, address p1, address p2, bool p3) internal pure {
5596 | | bytes32 m0;
5597 | | bytes32 m1;
5598 | | bytes32 m2;
5599 | | bytes32 m3;
5600 | | bytes32 m4;
5601 | | /// @solidity memory-safe-assembly
5602 | | assembly {
5603 | | m0 := mload(0x00)
5604 | | m1 := mload(0x20)
5605 | | m2 := mload(0x40)
5606 | | m3 := mload(0x60)
5607 | | m4 := mload(0x80)
5608 | | // Selector of `log(bool,address,address,bool)`.
5609 | | mstore(0x00, 0x46600be0)
5610 | | mstore(0x20, p0)
5611 | | mstore(0x40, p1)
5612 | | mstore(0x60, p2)
5613 | | mstore(0x80, p3)
5614 | | }
5615 | | _sendLogPayload(0x1c, 0x84);
5616 | | /// @solidity memory-safe-assembly
5617 | | assembly {
5618 | | mstore(0x00, m0)
5619 | | mstore(0x20, m1)
5620 | | mstore(0x40, m2)
5621 | | mstore(0x60, m3)
5622 | | mstore(0x80, m4)
5623 | | }
5624 | | }
5625 | |
5626 | | function log(bool p0, address p1, address p2, uint256 p3) internal pure {
5627 | | bytes32 m0;
5628 | | bytes32 m1;
5629 | | bytes32 m2;
5630 | | bytes32 m3;
5631 | | bytes32 m4;
5632 | | /// @solidity memory-safe-assembly
5633 | | assembly {
5634 | | m0 := mload(0x00)
5635 | | m1 := mload(0x20)
5636 | | m2 := mload(0x40)
5637 | | m3 := mload(0x60)
5638 | | m4 := mload(0x80)
5639 | | // Selector of `log(bool,address,address,uint256)`.
5640 | | mstore(0x00, 0x0c66d1be)
5641 | | mstore(0x20, p0)
5642 | | mstore(0x40, p1)
5643 | | mstore(0x60, p2)
5644 | | mstore(0x80, p3)
5645 | | }
5646 | | _sendLogPayload(0x1c, 0x84);
5647 | | /// @solidity memory-safe-assembly
5648 | | assembly {
5649 | | mstore(0x00, m0)
5650 | | mstore(0x20, m1)
5651 | | mstore(0x40, m2)
5652 | | mstore(0x60, m3)
5653 | | mstore(0x80, m4)
5654 | | }
5655 | | }
5656 | |
5657 | | function log(bool p0, address p1, address p2, bytes32 p3) internal pure {
5658 | | bytes32 m0;
5659 | | bytes32 m1;
5660 | | bytes32 m2;
5661 | | bytes32 m3;
5662 | | bytes32 m4;
5663 | | bytes32 m5;
5664 | | bytes32 m6;
5665 | | /// @solidity memory-safe-assembly
5666 | | assembly {
5667 | | function writeString(pos, w) {
5668 | | let length := 0
5669 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5670 | | mstore(pos, length)
5671 | | let shift := sub(256, shl(3, length))
5672 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5673 | | }
5674 | | m0 := mload(0x00)
5675 | | m1 := mload(0x20)
5676 | | m2 := mload(0x40)
5677 | | m3 := mload(0x60)
5678 | | m4 := mload(0x80)
5679 | | m5 := mload(0xa0)
5680 | | m6 := mload(0xc0)
5681 | | // Selector of `log(bool,address,address,string)`.
5682 | | mstore(0x00, 0xd812a167)
5683 | | mstore(0x20, p0)
5684 | | mstore(0x40, p1)
5685 | | mstore(0x60, p2)
5686 | | mstore(0x80, 0x80)
5687 | | writeString(0xa0, p3)
5688 | | }
5689 | | _sendLogPayload(0x1c, 0xc4);
5690 | | /// @solidity memory-safe-assembly
5691 | | assembly {
5692 | | mstore(0x00, m0)
5693 | | mstore(0x20, m1)
5694 | | mstore(0x40, m2)
5695 | | mstore(0x60, m3)
5696 | | mstore(0x80, m4)
5697 | | mstore(0xa0, m5)
5698 | | mstore(0xc0, m6)
5699 | | }
5700 | | }
5701 | |
5702 | | function log(bool p0, address p1, bool p2, address p3) internal pure {
5703 | | bytes32 m0;
5704 | | bytes32 m1;
5705 | | bytes32 m2;
5706 | | bytes32 m3;
5707 | | bytes32 m4;
5708 | | /// @solidity memory-safe-assembly
5709 | | assembly {
5710 | | m0 := mload(0x00)
5711 | | m1 := mload(0x20)
5712 | | m2 := mload(0x40)
5713 | | m3 := mload(0x60)
5714 | | m4 := mload(0x80)
5715 | | // Selector of `log(bool,address,bool,address)`.
5716 | | mstore(0x00, 0x1c41a336)
5717 | | mstore(0x20, p0)
5718 | | mstore(0x40, p1)
5719 | | mstore(0x60, p2)
5720 | | mstore(0x80, p3)
5721 | | }
5722 | | _sendLogPayload(0x1c, 0x84);
5723 | | /// @solidity memory-safe-assembly
5724 | | assembly {
5725 | | mstore(0x00, m0)
5726 | | mstore(0x20, m1)
5727 | | mstore(0x40, m2)
5728 | | mstore(0x60, m3)
5729 | | mstore(0x80, m4)
5730 | | }
5731 | | }
5732 | |
5733 | | function log(bool p0, address p1, bool p2, bool p3) internal pure {
5734 | | bytes32 m0;
5735 | | bytes32 m1;
5736 | | bytes32 m2;
5737 | | bytes32 m3;
5738 | | bytes32 m4;
5739 | | /// @solidity memory-safe-assembly
5740 | | assembly {
5741 | | m0 := mload(0x00)
5742 | | m1 := mload(0x20)
5743 | | m2 := mload(0x40)
5744 | | m3 := mload(0x60)
5745 | | m4 := mload(0x80)
5746 | | // Selector of `log(bool,address,bool,bool)`.
5747 | | mstore(0x00, 0x6a9c478b)
5748 | | mstore(0x20, p0)
5749 | | mstore(0x40, p1)
5750 | | mstore(0x60, p2)
5751 | | mstore(0x80, p3)
5752 | | }
5753 | | _sendLogPayload(0x1c, 0x84);
5754 | | /// @solidity memory-safe-assembly
5755 | | assembly {
5756 | | mstore(0x00, m0)
5757 | | mstore(0x20, m1)
5758 | | mstore(0x40, m2)
5759 | | mstore(0x60, m3)
5760 | | mstore(0x80, m4)
5761 | | }
5762 | | }
5763 | |
5764 | | function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
5765 | | bytes32 m0;
5766 | | bytes32 m1;
5767 | | bytes32 m2;
5768 | | bytes32 m3;
5769 | | bytes32 m4;
5770 | | /// @solidity memory-safe-assembly
5771 | | assembly {
5772 | | m0 := mload(0x00)
5773 | | m1 := mload(0x20)
5774 | | m2 := mload(0x40)
5775 | | m3 := mload(0x60)
5776 | | m4 := mload(0x80)
5777 | | // Selector of `log(bool,address,bool,uint256)`.
5778 | | mstore(0x00, 0x07831502)
5779 | | mstore(0x20, p0)
5780 | | mstore(0x40, p1)
5781 | | mstore(0x60, p2)
5782 | | mstore(0x80, p3)
5783 | | }
5784 | | _sendLogPayload(0x1c, 0x84);
5785 | | /// @solidity memory-safe-assembly
5786 | | assembly {
5787 | | mstore(0x00, m0)
5788 | | mstore(0x20, m1)
5789 | | mstore(0x40, m2)
5790 | | mstore(0x60, m3)
5791 | | mstore(0x80, m4)
5792 | | }
5793 | | }
5794 | |
5795 | | function log(bool p0, address p1, bool p2, bytes32 p3) internal pure {
5796 | | bytes32 m0;
5797 | | bytes32 m1;
5798 | | bytes32 m2;
5799 | | bytes32 m3;
5800 | | bytes32 m4;
5801 | | bytes32 m5;
5802 | | bytes32 m6;
5803 | | /// @solidity memory-safe-assembly
5804 | | assembly {
5805 | | function writeString(pos, w) {
5806 | | let length := 0
5807 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5808 | | mstore(pos, length)
5809 | | let shift := sub(256, shl(3, length))
5810 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5811 | | }
5812 | | m0 := mload(0x00)
5813 | | m1 := mload(0x20)
5814 | | m2 := mload(0x40)
5815 | | m3 := mload(0x60)
5816 | | m4 := mload(0x80)
5817 | | m5 := mload(0xa0)
5818 | | m6 := mload(0xc0)
5819 | | // Selector of `log(bool,address,bool,string)`.
5820 | | mstore(0x00, 0x4a66cb34)
5821 | | mstore(0x20, p0)
5822 | | mstore(0x40, p1)
5823 | | mstore(0x60, p2)
5824 | | mstore(0x80, 0x80)
5825 | | writeString(0xa0, p3)
5826 | | }
5827 | | _sendLogPayload(0x1c, 0xc4);
5828 | | /// @solidity memory-safe-assembly
5829 | | assembly {
5830 | | mstore(0x00, m0)
5831 | | mstore(0x20, m1)
5832 | | mstore(0x40, m2)
5833 | | mstore(0x60, m3)
5834 | | mstore(0x80, m4)
5835 | | mstore(0xa0, m5)
5836 | | mstore(0xc0, m6)
5837 | | }
5838 | | }
5839 | |
5840 | | function log(bool p0, address p1, uint256 p2, address p3) internal pure {
5841 | | bytes32 m0;
5842 | | bytes32 m1;
5843 | | bytes32 m2;
5844 | | bytes32 m3;
5845 | | bytes32 m4;
5846 | | /// @solidity memory-safe-assembly
5847 | | assembly {
5848 | | m0 := mload(0x00)
5849 | | m1 := mload(0x20)
5850 | | m2 := mload(0x40)
5851 | | m3 := mload(0x60)
5852 | | m4 := mload(0x80)
5853 | | // Selector of `log(bool,address,uint256,address)`.
5854 | | mstore(0x00, 0x136b05dd)
5855 | | mstore(0x20, p0)
5856 | | mstore(0x40, p1)
5857 | | mstore(0x60, p2)
5858 | | mstore(0x80, p3)
5859 | | }
5860 | | _sendLogPayload(0x1c, 0x84);
5861 | | /// @solidity memory-safe-assembly
5862 | | assembly {
5863 | | mstore(0x00, m0)
5864 | | mstore(0x20, m1)
5865 | | mstore(0x40, m2)
5866 | | mstore(0x60, m3)
5867 | | mstore(0x80, m4)
5868 | | }
5869 | | }
5870 | |
5871 | | function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
5872 | | bytes32 m0;
5873 | | bytes32 m1;
5874 | | bytes32 m2;
5875 | | bytes32 m3;
5876 | | bytes32 m4;
5877 | | /// @solidity memory-safe-assembly
5878 | | assembly {
5879 | | m0 := mload(0x00)
5880 | | m1 := mload(0x20)
5881 | | m2 := mload(0x40)
5882 | | m3 := mload(0x60)
5883 | | m4 := mload(0x80)
5884 | | // Selector of `log(bool,address,uint256,bool)`.
5885 | | mstore(0x00, 0xd6019f1c)
5886 | | mstore(0x20, p0)
5887 | | mstore(0x40, p1)
5888 | | mstore(0x60, p2)
5889 | | mstore(0x80, p3)
5890 | | }
5891 | | _sendLogPayload(0x1c, 0x84);
5892 | | /// @solidity memory-safe-assembly
5893 | | assembly {
5894 | | mstore(0x00, m0)
5895 | | mstore(0x20, m1)
5896 | | mstore(0x40, m2)
5897 | | mstore(0x60, m3)
5898 | | mstore(0x80, m4)
5899 | | }
5900 | | }
5901 | |
5902 | | function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
5903 | | bytes32 m0;
5904 | | bytes32 m1;
5905 | | bytes32 m2;
5906 | | bytes32 m3;
5907 | | bytes32 m4;
5908 | | /// @solidity memory-safe-assembly
5909 | | assembly {
5910 | | m0 := mload(0x00)
5911 | | m1 := mload(0x20)
5912 | | m2 := mload(0x40)
5913 | | m3 := mload(0x60)
5914 | | m4 := mload(0x80)
5915 | | // Selector of `log(bool,address,uint256,uint256)`.
5916 | | mstore(0x00, 0x7bf181a1)
5917 | | mstore(0x20, p0)
5918 | | mstore(0x40, p1)
5919 | | mstore(0x60, p2)
5920 | | mstore(0x80, p3)
5921 | | }
5922 | | _sendLogPayload(0x1c, 0x84);
5923 | | /// @solidity memory-safe-assembly
5924 | | assembly {
5925 | | mstore(0x00, m0)
5926 | | mstore(0x20, m1)
5927 | | mstore(0x40, m2)
5928 | | mstore(0x60, m3)
5929 | | mstore(0x80, m4)
5930 | | }
5931 | | }
5932 | |
5933 | | function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure {
5934 | | bytes32 m0;
5935 | | bytes32 m1;
5936 | | bytes32 m2;
5937 | | bytes32 m3;
5938 | | bytes32 m4;
5939 | | bytes32 m5;
5940 | | bytes32 m6;
5941 | | /// @solidity memory-safe-assembly
5942 | | assembly {
5943 | | function writeString(pos, w) {
5944 | | let length := 0
5945 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5946 | | mstore(pos, length)
5947 | | let shift := sub(256, shl(3, length))
5948 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5949 | | }
5950 | | m0 := mload(0x00)
5951 | | m1 := mload(0x20)
5952 | | m2 := mload(0x40)
5953 | | m3 := mload(0x60)
5954 | | m4 := mload(0x80)
5955 | | m5 := mload(0xa0)
5956 | | m6 := mload(0xc0)
5957 | | // Selector of `log(bool,address,uint256,string)`.
5958 | | mstore(0x00, 0x51f09ff8)
5959 | | mstore(0x20, p0)
5960 | | mstore(0x40, p1)
5961 | | mstore(0x60, p2)
5962 | | mstore(0x80, 0x80)
5963 | | writeString(0xa0, p3)
5964 | | }
5965 | | _sendLogPayload(0x1c, 0xc4);
5966 | | /// @solidity memory-safe-assembly
5967 | | assembly {
5968 | | mstore(0x00, m0)
5969 | | mstore(0x20, m1)
5970 | | mstore(0x40, m2)
5971 | | mstore(0x60, m3)
5972 | | mstore(0x80, m4)
5973 | | mstore(0xa0, m5)
5974 | | mstore(0xc0, m6)
5975 | | }
5976 | | }
5977 | |
5978 | | function log(bool p0, address p1, bytes32 p2, address p3) internal pure {
5979 | | bytes32 m0;
5980 | | bytes32 m1;
5981 | | bytes32 m2;
5982 | | bytes32 m3;
5983 | | bytes32 m4;
5984 | | bytes32 m5;
5985 | | bytes32 m6;
5986 | | /// @solidity memory-safe-assembly
5987 | | assembly {
5988 | | function writeString(pos, w) {
5989 | | let length := 0
5990 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5991 | | mstore(pos, length)
5992 | | let shift := sub(256, shl(3, length))
5993 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5994 | | }
5995 | | m0 := mload(0x00)
5996 | | m1 := mload(0x20)
5997 | | m2 := mload(0x40)
5998 | | m3 := mload(0x60)
5999 | | m4 := mload(0x80)
6000 | | m5 := mload(0xa0)
6001 | | m6 := mload(0xc0)
6002 | | // Selector of `log(bool,address,string,address)`.
6003 | | mstore(0x00, 0x6f7c603e)
6004 | | mstore(0x20, p0)
6005 | | mstore(0x40, p1)
6006 | | mstore(0x60, 0x80)
6007 | | mstore(0x80, p3)
6008 | | writeString(0xa0, p2)
6009 | | }
6010 | | _sendLogPayload(0x1c, 0xc4);
6011 | | /// @solidity memory-safe-assembly
6012 | | assembly {
6013 | | mstore(0x00, m0)
6014 | | mstore(0x20, m1)
6015 | | mstore(0x40, m2)
6016 | | mstore(0x60, m3)
6017 | | mstore(0x80, m4)
6018 | | mstore(0xa0, m5)
6019 | | mstore(0xc0, m6)
6020 | | }
6021 | | }
6022 | |
6023 | | function log(bool p0, address p1, bytes32 p2, bool p3) internal pure {
6024 | | bytes32 m0;
6025 | | bytes32 m1;
6026 | | bytes32 m2;
6027 | | bytes32 m3;
6028 | | bytes32 m4;
6029 | | bytes32 m5;
6030 | | bytes32 m6;
6031 | | /// @solidity memory-safe-assembly
6032 | | assembly {
6033 | | function writeString(pos, w) {
6034 | | let length := 0
6035 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6036 | | mstore(pos, length)
6037 | | let shift := sub(256, shl(3, length))
6038 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6039 | | }
6040 | | m0 := mload(0x00)
6041 | | m1 := mload(0x20)
6042 | | m2 := mload(0x40)
6043 | | m3 := mload(0x60)
6044 | | m4 := mload(0x80)
6045 | | m5 := mload(0xa0)
6046 | | m6 := mload(0xc0)
6047 | | // Selector of `log(bool,address,string,bool)`.
6048 | | mstore(0x00, 0xe2bfd60b)
6049 | | mstore(0x20, p0)
6050 | | mstore(0x40, p1)
6051 | | mstore(0x60, 0x80)
6052 | | mstore(0x80, p3)
6053 | | writeString(0xa0, p2)
6054 | | }
6055 | | _sendLogPayload(0x1c, 0xc4);
6056 | | /// @solidity memory-safe-assembly
6057 | | assembly {
6058 | | mstore(0x00, m0)
6059 | | mstore(0x20, m1)
6060 | | mstore(0x40, m2)
6061 | | mstore(0x60, m3)
6062 | | mstore(0x80, m4)
6063 | | mstore(0xa0, m5)
6064 | | mstore(0xc0, m6)
6065 | | }
6066 | | }
6067 | |
6068 | | function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure {
6069 | | bytes32 m0;
6070 | | bytes32 m1;
6071 | | bytes32 m2;
6072 | | bytes32 m3;
6073 | | bytes32 m4;
6074 | | bytes32 m5;
6075 | | bytes32 m6;
6076 | | /// @solidity memory-safe-assembly
6077 | | assembly {
6078 | | function writeString(pos, w) {
6079 | | let length := 0
6080 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6081 | | mstore(pos, length)
6082 | | let shift := sub(256, shl(3, length))
6083 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6084 | | }
6085 | | m0 := mload(0x00)
6086 | | m1 := mload(0x20)
6087 | | m2 := mload(0x40)
6088 | | m3 := mload(0x60)
6089 | | m4 := mload(0x80)
6090 | | m5 := mload(0xa0)
6091 | | m6 := mload(0xc0)
6092 | | // Selector of `log(bool,address,string,uint256)`.
6093 | | mstore(0x00, 0xc21f64c7)
6094 | | mstore(0x20, p0)
6095 | | mstore(0x40, p1)
6096 | | mstore(0x60, 0x80)
6097 | | mstore(0x80, p3)
6098 | | writeString(0xa0, p2)
6099 | | }
6100 | | _sendLogPayload(0x1c, 0xc4);
6101 | | /// @solidity memory-safe-assembly
6102 | | assembly {
6103 | | mstore(0x00, m0)
6104 | | mstore(0x20, m1)
6105 | | mstore(0x40, m2)
6106 | | mstore(0x60, m3)
6107 | | mstore(0x80, m4)
6108 | | mstore(0xa0, m5)
6109 | | mstore(0xc0, m6)
6110 | | }
6111 | | }
6112 | |
6113 | | function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure {
6114 | | bytes32 m0;
6115 | | bytes32 m1;
6116 | | bytes32 m2;
6117 | | bytes32 m3;
6118 | | bytes32 m4;
6119 | | bytes32 m5;
6120 | | bytes32 m6;
6121 | | bytes32 m7;
6122 | | bytes32 m8;
6123 | | /// @solidity memory-safe-assembly
6124 | | assembly {
6125 | | function writeString(pos, w) {
6126 | | let length := 0
6127 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6128 | | mstore(pos, length)
6129 | | let shift := sub(256, shl(3, length))
6130 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6131 | | }
6132 | | m0 := mload(0x00)
6133 | | m1 := mload(0x20)
6134 | | m2 := mload(0x40)
6135 | | m3 := mload(0x60)
6136 | | m4 := mload(0x80)
6137 | | m5 := mload(0xa0)
6138 | | m6 := mload(0xc0)
6139 | | m7 := mload(0xe0)
6140 | | m8 := mload(0x100)
6141 | | // Selector of `log(bool,address,string,string)`.
6142 | | mstore(0x00, 0xa73c1db6)
6143 | | mstore(0x20, p0)
6144 | | mstore(0x40, p1)
6145 | | mstore(0x60, 0x80)
6146 | | mstore(0x80, 0xc0)
6147 | | writeString(0xa0, p2)
6148 | | writeString(0xe0, p3)
6149 | | }
6150 | | _sendLogPayload(0x1c, 0x104);
6151 | | /// @solidity memory-safe-assembly
6152 | | assembly {
6153 | | mstore(0x00, m0)
6154 | | mstore(0x20, m1)
6155 | | mstore(0x40, m2)
6156 | | mstore(0x60, m3)
6157 | | mstore(0x80, m4)
6158 | | mstore(0xa0, m5)
6159 | | mstore(0xc0, m6)
6160 | | mstore(0xe0, m7)
6161 | | mstore(0x100, m8)
6162 | | }
6163 | | }
6164 | |
6165 | | function log(bool p0, bool p1, address p2, address p3) internal pure {
6166 | | bytes32 m0;
6167 | | bytes32 m1;
6168 | | bytes32 m2;
6169 | | bytes32 m3;
6170 | | bytes32 m4;
6171 | | /// @solidity memory-safe-assembly
6172 | | assembly {
6173 | | m0 := mload(0x00)
6174 | | m1 := mload(0x20)
6175 | | m2 := mload(0x40)
6176 | | m3 := mload(0x60)
6177 | | m4 := mload(0x80)
6178 | | // Selector of `log(bool,bool,address,address)`.
6179 | | mstore(0x00, 0xf4880ea4)
6180 | | mstore(0x20, p0)
6181 | | mstore(0x40, p1)
6182 | | mstore(0x60, p2)
6183 | | mstore(0x80, p3)
6184 | | }
6185 | | _sendLogPayload(0x1c, 0x84);
6186 | | /// @solidity memory-safe-assembly
6187 | | assembly {
6188 | | mstore(0x00, m0)
6189 | | mstore(0x20, m1)
6190 | | mstore(0x40, m2)
6191 | | mstore(0x60, m3)
6192 | | mstore(0x80, m4)
6193 | | }
6194 | | }
6195 | |
6196 | | function log(bool p0, bool p1, address p2, bool p3) internal pure {
6197 | | bytes32 m0;
6198 | | bytes32 m1;
6199 | | bytes32 m2;
6200 | | bytes32 m3;
6201 | | bytes32 m4;
6202 | | /// @solidity memory-safe-assembly
6203 | | assembly {
6204 | | m0 := mload(0x00)
6205 | | m1 := mload(0x20)
6206 | | m2 := mload(0x40)
6207 | | m3 := mload(0x60)
6208 | | m4 := mload(0x80)
6209 | | // Selector of `log(bool,bool,address,bool)`.
6210 | | mstore(0x00, 0xc0a302d8)
6211 | | mstore(0x20, p0)
6212 | | mstore(0x40, p1)
6213 | | mstore(0x60, p2)
6214 | | mstore(0x80, p3)
6215 | | }
6216 | | _sendLogPayload(0x1c, 0x84);
6217 | | /// @solidity memory-safe-assembly
6218 | | assembly {
6219 | | mstore(0x00, m0)
6220 | | mstore(0x20, m1)
6221 | | mstore(0x40, m2)
6222 | | mstore(0x60, m3)
6223 | | mstore(0x80, m4)
6224 | | }
6225 | | }
6226 | |
6227 | | function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
6228 | | bytes32 m0;
6229 | | bytes32 m1;
6230 | | bytes32 m2;
6231 | | bytes32 m3;
6232 | | bytes32 m4;
6233 | | /// @solidity memory-safe-assembly
6234 | | assembly {
6235 | | m0 := mload(0x00)
6236 | | m1 := mload(0x20)
6237 | | m2 := mload(0x40)
6238 | | m3 := mload(0x60)
6239 | | m4 := mload(0x80)
6240 | | // Selector of `log(bool,bool,address,uint256)`.
6241 | | mstore(0x00, 0x4c123d57)
6242 | | mstore(0x20, p0)
6243 | | mstore(0x40, p1)
6244 | | mstore(0x60, p2)
6245 | | mstore(0x80, p3)
6246 | | }
6247 | | _sendLogPayload(0x1c, 0x84);
6248 | | /// @solidity memory-safe-assembly
6249 | | assembly {
6250 | | mstore(0x00, m0)
6251 | | mstore(0x20, m1)
6252 | | mstore(0x40, m2)
6253 | | mstore(0x60, m3)
6254 | | mstore(0x80, m4)
6255 | | }
6256 | | }
6257 | |
6258 | | function log(bool p0, bool p1, address p2, bytes32 p3) internal pure {
6259 | | bytes32 m0;
6260 | | bytes32 m1;
6261 | | bytes32 m2;
6262 | | bytes32 m3;
6263 | | bytes32 m4;
6264 | | bytes32 m5;
6265 | | bytes32 m6;
6266 | | /// @solidity memory-safe-assembly
6267 | | assembly {
6268 | | function writeString(pos, w) {
6269 | | let length := 0
6270 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6271 | | mstore(pos, length)
6272 | | let shift := sub(256, shl(3, length))
6273 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6274 | | }
6275 | | m0 := mload(0x00)
6276 | | m1 := mload(0x20)
6277 | | m2 := mload(0x40)
6278 | | m3 := mload(0x60)
6279 | | m4 := mload(0x80)
6280 | | m5 := mload(0xa0)
6281 | | m6 := mload(0xc0)
6282 | | // Selector of `log(bool,bool,address,string)`.
6283 | | mstore(0x00, 0xa0a47963)
6284 | | mstore(0x20, p0)
6285 | | mstore(0x40, p1)
6286 | | mstore(0x60, p2)
6287 | | mstore(0x80, 0x80)
6288 | | writeString(0xa0, p3)
6289 | | }
6290 | | _sendLogPayload(0x1c, 0xc4);
6291 | | /// @solidity memory-safe-assembly
6292 | | assembly {
6293 | | mstore(0x00, m0)
6294 | | mstore(0x20, m1)
6295 | | mstore(0x40, m2)
6296 | | mstore(0x60, m3)
6297 | | mstore(0x80, m4)
6298 | | mstore(0xa0, m5)
6299 | | mstore(0xc0, m6)
6300 | | }
6301 | | }
6302 | |
6303 | | function log(bool p0, bool p1, bool p2, address p3) internal pure {
6304 | | bytes32 m0;
6305 | | bytes32 m1;
6306 | | bytes32 m2;
6307 | | bytes32 m3;
6308 | | bytes32 m4;
6309 | | /// @solidity memory-safe-assembly
6310 | | assembly {
6311 | | m0 := mload(0x00)
6312 | | m1 := mload(0x20)
6313 | | m2 := mload(0x40)
6314 | | m3 := mload(0x60)
6315 | | m4 := mload(0x80)
6316 | | // Selector of `log(bool,bool,bool,address)`.
6317 | | mstore(0x00, 0x8c329b1a)
6318 | | mstore(0x20, p0)
6319 | | mstore(0x40, p1)
6320 | | mstore(0x60, p2)
6321 | | mstore(0x80, p3)
6322 | | }
6323 | | _sendLogPayload(0x1c, 0x84);
6324 | | /// @solidity memory-safe-assembly
6325 | | assembly {
6326 | | mstore(0x00, m0)
6327 | | mstore(0x20, m1)
6328 | | mstore(0x40, m2)
6329 | | mstore(0x60, m3)
6330 | | mstore(0x80, m4)
6331 | | }
6332 | | }
6333 | |
6334 | | function log(bool p0, bool p1, bool p2, bool p3) internal pure {
6335 | | bytes32 m0;
6336 | | bytes32 m1;
6337 | | bytes32 m2;
6338 | | bytes32 m3;
6339 | | bytes32 m4;
6340 | | /// @solidity memory-safe-assembly
6341 | | assembly {
6342 | | m0 := mload(0x00)
6343 | | m1 := mload(0x20)
6344 | | m2 := mload(0x40)
6345 | | m3 := mload(0x60)
6346 | | m4 := mload(0x80)
6347 | | // Selector of `log(bool,bool,bool,bool)`.
6348 | | mstore(0x00, 0x3b2a5ce0)
6349 | | mstore(0x20, p0)
6350 | | mstore(0x40, p1)
6351 | | mstore(0x60, p2)
6352 | | mstore(0x80, p3)
6353 | | }
6354 | | _sendLogPayload(0x1c, 0x84);
6355 | | /// @solidity memory-safe-assembly
6356 | | assembly {
6357 | | mstore(0x00, m0)
6358 | | mstore(0x20, m1)
6359 | | mstore(0x40, m2)
6360 | | mstore(0x60, m3)
6361 | | mstore(0x80, m4)
6362 | | }
6363 | | }
6364 | |
6365 | | function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
6366 | | bytes32 m0;
6367 | | bytes32 m1;
6368 | | bytes32 m2;
6369 | | bytes32 m3;
6370 | | bytes32 m4;
6371 | | /// @solidity memory-safe-assembly
6372 | | assembly {
6373 | | m0 := mload(0x00)
6374 | | m1 := mload(0x20)
6375 | | m2 := mload(0x40)
6376 | | m3 := mload(0x60)
6377 | | m4 := mload(0x80)
6378 | | // Selector of `log(bool,bool,bool,uint256)`.
6379 | | mstore(0x00, 0x6d7045c1)
6380 | | mstore(0x20, p0)
6381 | | mstore(0x40, p1)
6382 | | mstore(0x60, p2)
6383 | | mstore(0x80, p3)
6384 | | }
6385 | | _sendLogPayload(0x1c, 0x84);
6386 | | /// @solidity memory-safe-assembly
6387 | | assembly {
6388 | | mstore(0x00, m0)
6389 | | mstore(0x20, m1)
6390 | | mstore(0x40, m2)
6391 | | mstore(0x60, m3)
6392 | | mstore(0x80, m4)
6393 | | }
6394 | | }
6395 | |
6396 | | function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure {
6397 | | bytes32 m0;
6398 | | bytes32 m1;
6399 | | bytes32 m2;
6400 | | bytes32 m3;
6401 | | bytes32 m4;
6402 | | bytes32 m5;
6403 | | bytes32 m6;
6404 | | /// @solidity memory-safe-assembly
6405 | | assembly {
6406 | | function writeString(pos, w) {
6407 | | let length := 0
6408 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6409 | | mstore(pos, length)
6410 | | let shift := sub(256, shl(3, length))
6411 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6412 | | }
6413 | | m0 := mload(0x00)
6414 | | m1 := mload(0x20)
6415 | | m2 := mload(0x40)
6416 | | m3 := mload(0x60)
6417 | | m4 := mload(0x80)
6418 | | m5 := mload(0xa0)
6419 | | m6 := mload(0xc0)
6420 | | // Selector of `log(bool,bool,bool,string)`.
6421 | | mstore(0x00, 0x2ae408d4)
6422 | | mstore(0x20, p0)
6423 | | mstore(0x40, p1)
6424 | | mstore(0x60, p2)
6425 | | mstore(0x80, 0x80)
6426 | | writeString(0xa0, p3)
6427 | | }
6428 | | _sendLogPayload(0x1c, 0xc4);
6429 | | /// @solidity memory-safe-assembly
6430 | | assembly {
6431 | | mstore(0x00, m0)
6432 | | mstore(0x20, m1)
6433 | | mstore(0x40, m2)
6434 | | mstore(0x60, m3)
6435 | | mstore(0x80, m4)
6436 | | mstore(0xa0, m5)
6437 | | mstore(0xc0, m6)
6438 | | }
6439 | | }
6440 | |
6441 | | function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
6442 | | bytes32 m0;
6443 | | bytes32 m1;
6444 | | bytes32 m2;
6445 | | bytes32 m3;
6446 | | bytes32 m4;
6447 | | /// @solidity memory-safe-assembly
6448 | | assembly {
6449 | | m0 := mload(0x00)
6450 | | m1 := mload(0x20)
6451 | | m2 := mload(0x40)
6452 | | m3 := mload(0x60)
6453 | | m4 := mload(0x80)
6454 | | // Selector of `log(bool,bool,uint256,address)`.
6455 | | mstore(0x00, 0x54a7a9a0)
6456 | | mstore(0x20, p0)
6457 | | mstore(0x40, p1)
6458 | | mstore(0x60, p2)
6459 | | mstore(0x80, p3)
6460 | | }
6461 | | _sendLogPayload(0x1c, 0x84);
6462 | | /// @solidity memory-safe-assembly
6463 | | assembly {
6464 | | mstore(0x00, m0)
6465 | | mstore(0x20, m1)
6466 | | mstore(0x40, m2)
6467 | | mstore(0x60, m3)
6468 | | mstore(0x80, m4)
6469 | | }
6470 | | }
6471 | |
6472 | | function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
6473 | | bytes32 m0;
6474 | | bytes32 m1;
6475 | | bytes32 m2;
6476 | | bytes32 m3;
6477 | | bytes32 m4;
6478 | | /// @solidity memory-safe-assembly
6479 | | assembly {
6480 | | m0 := mload(0x00)
6481 | | m1 := mload(0x20)
6482 | | m2 := mload(0x40)
6483 | | m3 := mload(0x60)
6484 | | m4 := mload(0x80)
6485 | | // Selector of `log(bool,bool,uint256,bool)`.
6486 | | mstore(0x00, 0x619e4d0e)
6487 | | mstore(0x20, p0)
6488 | | mstore(0x40, p1)
6489 | | mstore(0x60, p2)
6490 | | mstore(0x80, p3)
6491 | | }
6492 | | _sendLogPayload(0x1c, 0x84);
6493 | | /// @solidity memory-safe-assembly
6494 | | assembly {
6495 | | mstore(0x00, m0)
6496 | | mstore(0x20, m1)
6497 | | mstore(0x40, m2)
6498 | | mstore(0x60, m3)
6499 | | mstore(0x80, m4)
6500 | | }
6501 | | }
6502 | |
6503 | | function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
6504 | | bytes32 m0;
6505 | | bytes32 m1;
6506 | | bytes32 m2;
6507 | | bytes32 m3;
6508 | | bytes32 m4;
6509 | | /// @solidity memory-safe-assembly
6510 | | assembly {
6511 | | m0 := mload(0x00)
6512 | | m1 := mload(0x20)
6513 | | m2 := mload(0x40)
6514 | | m3 := mload(0x60)
6515 | | m4 := mload(0x80)
6516 | | // Selector of `log(bool,bool,uint256,uint256)`.
6517 | | mstore(0x00, 0x0bb00eab)
6518 | | mstore(0x20, p0)
6519 | | mstore(0x40, p1)
6520 | | mstore(0x60, p2)
6521 | | mstore(0x80, p3)
6522 | | }
6523 | | _sendLogPayload(0x1c, 0x84);
6524 | | /// @solidity memory-safe-assembly
6525 | | assembly {
6526 | | mstore(0x00, m0)
6527 | | mstore(0x20, m1)
6528 | | mstore(0x40, m2)
6529 | | mstore(0x60, m3)
6530 | | mstore(0x80, m4)
6531 | | }
6532 | | }
6533 | |
6534 | | function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure {
6535 | | bytes32 m0;
6536 | | bytes32 m1;
6537 | | bytes32 m2;
6538 | | bytes32 m3;
6539 | | bytes32 m4;
6540 | | bytes32 m5;
6541 | | bytes32 m6;
6542 | | /// @solidity memory-safe-assembly
6543 | | assembly {
6544 | | function writeString(pos, w) {
6545 | | let length := 0
6546 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6547 | | mstore(pos, length)
6548 | | let shift := sub(256, shl(3, length))
6549 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6550 | | }
6551 | | m0 := mload(0x00)
6552 | | m1 := mload(0x20)
6553 | | m2 := mload(0x40)
6554 | | m3 := mload(0x60)
6555 | | m4 := mload(0x80)
6556 | | m5 := mload(0xa0)
6557 | | m6 := mload(0xc0)
6558 | | // Selector of `log(bool,bool,uint256,string)`.
6559 | | mstore(0x00, 0x7dd4d0e0)
6560 | | mstore(0x20, p0)
6561 | | mstore(0x40, p1)
6562 | | mstore(0x60, p2)
6563 | | mstore(0x80, 0x80)
6564 | | writeString(0xa0, p3)
6565 | | }
6566 | | _sendLogPayload(0x1c, 0xc4);
6567 | | /// @solidity memory-safe-assembly
6568 | | assembly {
6569 | | mstore(0x00, m0)
6570 | | mstore(0x20, m1)
6571 | | mstore(0x40, m2)
6572 | | mstore(0x60, m3)
6573 | | mstore(0x80, m4)
6574 | | mstore(0xa0, m5)
6575 | | mstore(0xc0, m6)
6576 | | }
6577 | | }
6578 | |
6579 | | function log(bool p0, bool p1, bytes32 p2, address p3) internal pure {
6580 | | bytes32 m0;
6581 | | bytes32 m1;
6582 | | bytes32 m2;
6583 | | bytes32 m3;
6584 | | bytes32 m4;
6585 | | bytes32 m5;
6586 | | bytes32 m6;
6587 | | /// @solidity memory-safe-assembly
6588 | | assembly {
6589 | | function writeString(pos, w) {
6590 | | let length := 0
6591 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6592 | | mstore(pos, length)
6593 | | let shift := sub(256, shl(3, length))
6594 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6595 | | }
6596 | | m0 := mload(0x00)
6597 | | m1 := mload(0x20)
6598 | | m2 := mload(0x40)
6599 | | m3 := mload(0x60)
6600 | | m4 := mload(0x80)
6601 | | m5 := mload(0xa0)
6602 | | m6 := mload(0xc0)
6603 | | // Selector of `log(bool,bool,string,address)`.
6604 | | mstore(0x00, 0xf9ad2b89)
6605 | | mstore(0x20, p0)
6606 | | mstore(0x40, p1)
6607 | | mstore(0x60, 0x80)
6608 | | mstore(0x80, p3)
6609 | | writeString(0xa0, p2)
6610 | | }
6611 | | _sendLogPayload(0x1c, 0xc4);
6612 | | /// @solidity memory-safe-assembly
6613 | | assembly {
6614 | | mstore(0x00, m0)
6615 | | mstore(0x20, m1)
6616 | | mstore(0x40, m2)
6617 | | mstore(0x60, m3)
6618 | | mstore(0x80, m4)
6619 | | mstore(0xa0, m5)
6620 | | mstore(0xc0, m6)
6621 | | }
6622 | | }
6623 | |
6624 | | function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure {
6625 | | bytes32 m0;
6626 | | bytes32 m1;
6627 | | bytes32 m2;
6628 | | bytes32 m3;
6629 | | bytes32 m4;
6630 | | bytes32 m5;
6631 | | bytes32 m6;
6632 | | /// @solidity memory-safe-assembly
6633 | | assembly {
6634 | | function writeString(pos, w) {
6635 | | let length := 0
6636 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6637 | | mstore(pos, length)
6638 | | let shift := sub(256, shl(3, length))
6639 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6640 | | }
6641 | | m0 := mload(0x00)
6642 | | m1 := mload(0x20)
6643 | | m2 := mload(0x40)
6644 | | m3 := mload(0x60)
6645 | | m4 := mload(0x80)
6646 | | m5 := mload(0xa0)
6647 | | m6 := mload(0xc0)
6648 | | // Selector of `log(bool,bool,string,bool)`.
6649 | | mstore(0x00, 0xb857163a)
6650 | | mstore(0x20, p0)
6651 | | mstore(0x40, p1)
6652 | | mstore(0x60, 0x80)
6653 | | mstore(0x80, p3)
6654 | | writeString(0xa0, p2)
6655 | | }
6656 | | _sendLogPayload(0x1c, 0xc4);
6657 | | /// @solidity memory-safe-assembly
6658 | | assembly {
6659 | | mstore(0x00, m0)
6660 | | mstore(0x20, m1)
6661 | | mstore(0x40, m2)
6662 | | mstore(0x60, m3)
6663 | | mstore(0x80, m4)
6664 | | mstore(0xa0, m5)
6665 | | mstore(0xc0, m6)
6666 | | }
6667 | | }
6668 | |
6669 | | function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure {
6670 | | bytes32 m0;
6671 | | bytes32 m1;
6672 | | bytes32 m2;
6673 | | bytes32 m3;
6674 | | bytes32 m4;
6675 | | bytes32 m5;
6676 | | bytes32 m6;
6677 | | /// @solidity memory-safe-assembly
6678 | | assembly {
6679 | | function writeString(pos, w) {
6680 | | let length := 0
6681 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6682 | | mstore(pos, length)
6683 | | let shift := sub(256, shl(3, length))
6684 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6685 | | }
6686 | | m0 := mload(0x00)
6687 | | m1 := mload(0x20)
6688 | | m2 := mload(0x40)
6689 | | m3 := mload(0x60)
6690 | | m4 := mload(0x80)
6691 | | m5 := mload(0xa0)
6692 | | m6 := mload(0xc0)
6693 | | // Selector of `log(bool,bool,string,uint256)`.
6694 | | mstore(0x00, 0xe3a9ca2f)
6695 | | mstore(0x20, p0)
6696 | | mstore(0x40, p1)
6697 | | mstore(0x60, 0x80)
6698 | | mstore(0x80, p3)
6699 | | writeString(0xa0, p2)
6700 | | }
6701 | | _sendLogPayload(0x1c, 0xc4);
6702 | | /// @solidity memory-safe-assembly
6703 | | assembly {
6704 | | mstore(0x00, m0)
6705 | | mstore(0x20, m1)
6706 | | mstore(0x40, m2)
6707 | | mstore(0x60, m3)
6708 | | mstore(0x80, m4)
6709 | | mstore(0xa0, m5)
6710 | | mstore(0xc0, m6)
6711 | | }
6712 | | }
6713 | |
6714 | | function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
6715 | | bytes32 m0;
6716 | | bytes32 m1;
6717 | | bytes32 m2;
6718 | | bytes32 m3;
6719 | | bytes32 m4;
6720 | | bytes32 m5;
6721 | | bytes32 m6;
6722 | | bytes32 m7;
6723 | | bytes32 m8;
6724 | | /// @solidity memory-safe-assembly
6725 | | assembly {
6726 | | function writeString(pos, w) {
6727 | | let length := 0
6728 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6729 | | mstore(pos, length)
6730 | | let shift := sub(256, shl(3, length))
6731 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6732 | | }
6733 | | m0 := mload(0x00)
6734 | | m1 := mload(0x20)
6735 | | m2 := mload(0x40)
6736 | | m3 := mload(0x60)
6737 | | m4 := mload(0x80)
6738 | | m5 := mload(0xa0)
6739 | | m6 := mload(0xc0)
6740 | | m7 := mload(0xe0)
6741 | | m8 := mload(0x100)
6742 | | // Selector of `log(bool,bool,string,string)`.
6743 | | mstore(0x00, 0x6d1e8751)
6744 | | mstore(0x20, p0)
6745 | | mstore(0x40, p1)
6746 | | mstore(0x60, 0x80)
6747 | | mstore(0x80, 0xc0)
6748 | | writeString(0xa0, p2)
6749 | | writeString(0xe0, p3)
6750 | | }
6751 | | _sendLogPayload(0x1c, 0x104);
6752 | | /// @solidity memory-safe-assembly
6753 | | assembly {
6754 | | mstore(0x00, m0)
6755 | | mstore(0x20, m1)
6756 | | mstore(0x40, m2)
6757 | | mstore(0x60, m3)
6758 | | mstore(0x80, m4)
6759 | | mstore(0xa0, m5)
6760 | | mstore(0xc0, m6)
6761 | | mstore(0xe0, m7)
6762 | | mstore(0x100, m8)
6763 | | }
6764 | | }
6765 | |
6766 | | function log(bool p0, uint256 p1, address p2, address p3) internal pure {
6767 | | bytes32 m0;
6768 | | bytes32 m1;
6769 | | bytes32 m2;
6770 | | bytes32 m3;
6771 | | bytes32 m4;
6772 | | /// @solidity memory-safe-assembly
6773 | | assembly {
6774 | | m0 := mload(0x00)
6775 | | m1 := mload(0x20)
6776 | | m2 := mload(0x40)
6777 | | m3 := mload(0x60)
6778 | | m4 := mload(0x80)
6779 | | // Selector of `log(bool,uint256,address,address)`.
6780 | | mstore(0x00, 0x26f560a8)
6781 | | mstore(0x20, p0)
6782 | | mstore(0x40, p1)
6783 | | mstore(0x60, p2)
6784 | | mstore(0x80, p3)
6785 | | }
6786 | | _sendLogPayload(0x1c, 0x84);
6787 | | /// @solidity memory-safe-assembly
6788 | | assembly {
6789 | | mstore(0x00, m0)
6790 | | mstore(0x20, m1)
6791 | | mstore(0x40, m2)
6792 | | mstore(0x60, m3)
6793 | | mstore(0x80, m4)
6794 | | }
6795 | | }
6796 | |
6797 | | function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
6798 | | bytes32 m0;
6799 | | bytes32 m1;
6800 | | bytes32 m2;
6801 | | bytes32 m3;
6802 | | bytes32 m4;
6803 | | /// @solidity memory-safe-assembly
6804 | | assembly {
6805 | | m0 := mload(0x00)
6806 | | m1 := mload(0x20)
6807 | | m2 := mload(0x40)
6808 | | m3 := mload(0x60)
6809 | | m4 := mload(0x80)
6810 | | // Selector of `log(bool,uint256,address,bool)`.
6811 | | mstore(0x00, 0xb4c314ff)
6812 | | mstore(0x20, p0)
6813 | | mstore(0x40, p1)
6814 | | mstore(0x60, p2)
6815 | | mstore(0x80, p3)
6816 | | }
6817 | | _sendLogPayload(0x1c, 0x84);
6818 | | /// @solidity memory-safe-assembly
6819 | | assembly {
6820 | | mstore(0x00, m0)
6821 | | mstore(0x20, m1)
6822 | | mstore(0x40, m2)
6823 | | mstore(0x60, m3)
6824 | | mstore(0x80, m4)
6825 | | }
6826 | | }
6827 | |
6828 | | function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
6829 | | bytes32 m0;
6830 | | bytes32 m1;
6831 | | bytes32 m2;
6832 | | bytes32 m3;
6833 | | bytes32 m4;
6834 | | /// @solidity memory-safe-assembly
6835 | | assembly {
6836 | | m0 := mload(0x00)
6837 | | m1 := mload(0x20)
6838 | | m2 := mload(0x40)
6839 | | m3 := mload(0x60)
6840 | | m4 := mload(0x80)
6841 | | // Selector of `log(bool,uint256,address,uint256)`.
6842 | | mstore(0x00, 0x1537dc87)
6843 | | mstore(0x20, p0)
6844 | | mstore(0x40, p1)
6845 | | mstore(0x60, p2)
6846 | | mstore(0x80, p3)
6847 | | }
6848 | | _sendLogPayload(0x1c, 0x84);
6849 | | /// @solidity memory-safe-assembly
6850 | | assembly {
6851 | | mstore(0x00, m0)
6852 | | mstore(0x20, m1)
6853 | | mstore(0x40, m2)
6854 | | mstore(0x60, m3)
6855 | | mstore(0x80, m4)
6856 | | }
6857 | | }
6858 | |
6859 | | function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure {
6860 | | bytes32 m0;
6861 | | bytes32 m1;
6862 | | bytes32 m2;
6863 | | bytes32 m3;
6864 | | bytes32 m4;
6865 | | bytes32 m5;
6866 | | bytes32 m6;
6867 | | /// @solidity memory-safe-assembly
6868 | | assembly {
6869 | | function writeString(pos, w) {
6870 | | let length := 0
6871 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6872 | | mstore(pos, length)
6873 | | let shift := sub(256, shl(3, length))
6874 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6875 | | }
6876 | | m0 := mload(0x00)
6877 | | m1 := mload(0x20)
6878 | | m2 := mload(0x40)
6879 | | m3 := mload(0x60)
6880 | | m4 := mload(0x80)
6881 | | m5 := mload(0xa0)
6882 | | m6 := mload(0xc0)
6883 | | // Selector of `log(bool,uint256,address,string)`.
6884 | | mstore(0x00, 0x1bb3b09a)
6885 | | mstore(0x20, p0)
6886 | | mstore(0x40, p1)
6887 | | mstore(0x60, p2)
6888 | | mstore(0x80, 0x80)
6889 | | writeString(0xa0, p3)
6890 | | }
6891 | | _sendLogPayload(0x1c, 0xc4);
6892 | | /// @solidity memory-safe-assembly
6893 | | assembly {
6894 | | mstore(0x00, m0)
6895 | | mstore(0x20, m1)
6896 | | mstore(0x40, m2)
6897 | | mstore(0x60, m3)
6898 | | mstore(0x80, m4)
6899 | | mstore(0xa0, m5)
6900 | | mstore(0xc0, m6)
6901 | | }
6902 | | }
6903 | |
6904 | | function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
6905 | | bytes32 m0;
6906 | | bytes32 m1;
6907 | | bytes32 m2;
6908 | | bytes32 m3;
6909 | | bytes32 m4;
6910 | | /// @solidity memory-safe-assembly
6911 | | assembly {
6912 | | m0 := mload(0x00)
6913 | | m1 := mload(0x20)
6914 | | m2 := mload(0x40)
6915 | | m3 := mload(0x60)
6916 | | m4 := mload(0x80)
6917 | | // Selector of `log(bool,uint256,bool,address)`.
6918 | | mstore(0x00, 0x9acd3616)
6919 | | mstore(0x20, p0)
6920 | | mstore(0x40, p1)
6921 | | mstore(0x60, p2)
6922 | | mstore(0x80, p3)
6923 | | }
6924 | | _sendLogPayload(0x1c, 0x84);
6925 | | /// @solidity memory-safe-assembly
6926 | | assembly {
6927 | | mstore(0x00, m0)
6928 | | mstore(0x20, m1)
6929 | | mstore(0x40, m2)
6930 | | mstore(0x60, m3)
6931 | | mstore(0x80, m4)
6932 | | }
6933 | | }
6934 | |
6935 | | function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
6936 | | bytes32 m0;
6937 | | bytes32 m1;
6938 | | bytes32 m2;
6939 | | bytes32 m3;
6940 | | bytes32 m4;
6941 | | /// @solidity memory-safe-assembly
6942 | | assembly {
6943 | | m0 := mload(0x00)
6944 | | m1 := mload(0x20)
6945 | | m2 := mload(0x40)
6946 | | m3 := mload(0x60)
6947 | | m4 := mload(0x80)
6948 | | // Selector of `log(bool,uint256,bool,bool)`.
6949 | | mstore(0x00, 0xceb5f4d7)
6950 | | mstore(0x20, p0)
6951 | | mstore(0x40, p1)
6952 | | mstore(0x60, p2)
6953 | | mstore(0x80, p3)
6954 | | }
6955 | | _sendLogPayload(0x1c, 0x84);
6956 | | /// @solidity memory-safe-assembly
6957 | | assembly {
6958 | | mstore(0x00, m0)
6959 | | mstore(0x20, m1)
6960 | | mstore(0x40, m2)
6961 | | mstore(0x60, m3)
6962 | | mstore(0x80, m4)
6963 | | }
6964 | | }
6965 | |
6966 | | function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
6967 | | bytes32 m0;
6968 | | bytes32 m1;
6969 | | bytes32 m2;
6970 | | bytes32 m3;
6971 | | bytes32 m4;
6972 | | /// @solidity memory-safe-assembly
6973 | | assembly {
6974 | | m0 := mload(0x00)
6975 | | m1 := mload(0x20)
6976 | | m2 := mload(0x40)
6977 | | m3 := mload(0x60)
6978 | | m4 := mload(0x80)
6979 | | // Selector of `log(bool,uint256,bool,uint256)`.
6980 | | mstore(0x00, 0x7f9bbca2)
6981 | | mstore(0x20, p0)
6982 | | mstore(0x40, p1)
6983 | | mstore(0x60, p2)
6984 | | mstore(0x80, p3)
6985 | | }
6986 | | _sendLogPayload(0x1c, 0x84);
6987 | | /// @solidity memory-safe-assembly
6988 | | assembly {
6989 | | mstore(0x00, m0)
6990 | | mstore(0x20, m1)
6991 | | mstore(0x40, m2)
6992 | | mstore(0x60, m3)
6993 | | mstore(0x80, m4)
6994 | | }
6995 | | }
6996 | |
6997 | | function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure {
6998 | | bytes32 m0;
6999 | | bytes32 m1;
7000 | | bytes32 m2;
7001 | | bytes32 m3;
7002 | | bytes32 m4;
7003 | | bytes32 m5;
7004 | | bytes32 m6;
7005 | | /// @solidity memory-safe-assembly
7006 | | assembly {
7007 | | function writeString(pos, w) {
7008 | | let length := 0
7009 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7010 | | mstore(pos, length)
7011 | | let shift := sub(256, shl(3, length))
7012 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7013 | | }
7014 | | m0 := mload(0x00)
7015 | | m1 := mload(0x20)
7016 | | m2 := mload(0x40)
7017 | | m3 := mload(0x60)
7018 | | m4 := mload(0x80)
7019 | | m5 := mload(0xa0)
7020 | | m6 := mload(0xc0)
7021 | | // Selector of `log(bool,uint256,bool,string)`.
7022 | | mstore(0x00, 0x9143dbb1)
7023 | | mstore(0x20, p0)
7024 | | mstore(0x40, p1)
7025 | | mstore(0x60, p2)
7026 | | mstore(0x80, 0x80)
7027 | | writeString(0xa0, p3)
7028 | | }
7029 | | _sendLogPayload(0x1c, 0xc4);
7030 | | /// @solidity memory-safe-assembly
7031 | | assembly {
7032 | | mstore(0x00, m0)
7033 | | mstore(0x20, m1)
7034 | | mstore(0x40, m2)
7035 | | mstore(0x60, m3)
7036 | | mstore(0x80, m4)
7037 | | mstore(0xa0, m5)
7038 | | mstore(0xc0, m6)
7039 | | }
7040 | | }
7041 | |
7042 | | function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
7043 | | bytes32 m0;
7044 | | bytes32 m1;
7045 | | bytes32 m2;
7046 | | bytes32 m3;
7047 | | bytes32 m4;
7048 | | /// @solidity memory-safe-assembly
7049 | | assembly {
7050 | | m0 := mload(0x00)
7051 | | m1 := mload(0x20)
7052 | | m2 := mload(0x40)
7053 | | m3 := mload(0x60)
7054 | | m4 := mload(0x80)
7055 | | // Selector of `log(bool,uint256,uint256,address)`.
7056 | | mstore(0x00, 0x00dd87b9)
7057 | | mstore(0x20, p0)
7058 | | mstore(0x40, p1)
7059 | | mstore(0x60, p2)
7060 | | mstore(0x80, p3)
7061 | | }
7062 | | _sendLogPayload(0x1c, 0x84);
7063 | | /// @solidity memory-safe-assembly
7064 | | assembly {
7065 | | mstore(0x00, m0)
7066 | | mstore(0x20, m1)
7067 | | mstore(0x40, m2)
7068 | | mstore(0x60, m3)
7069 | | mstore(0x80, m4)
7070 | | }
7071 | | }
7072 | |
7073 | | function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
7074 | | bytes32 m0;
7075 | | bytes32 m1;
7076 | | bytes32 m2;
7077 | | bytes32 m3;
7078 | | bytes32 m4;
7079 | | /// @solidity memory-safe-assembly
7080 | | assembly {
7081 | | m0 := mload(0x00)
7082 | | m1 := mload(0x20)
7083 | | m2 := mload(0x40)
7084 | | m3 := mload(0x60)
7085 | | m4 := mload(0x80)
7086 | | // Selector of `log(bool,uint256,uint256,bool)`.
7087 | | mstore(0x00, 0xbe984353)
7088 | | mstore(0x20, p0)
7089 | | mstore(0x40, p1)
7090 | | mstore(0x60, p2)
7091 | | mstore(0x80, p3)
7092 | | }
7093 | | _sendLogPayload(0x1c, 0x84);
7094 | | /// @solidity memory-safe-assembly
7095 | | assembly {
7096 | | mstore(0x00, m0)
7097 | | mstore(0x20, m1)
7098 | | mstore(0x40, m2)
7099 | | mstore(0x60, m3)
7100 | | mstore(0x80, m4)
7101 | | }
7102 | | }
7103 | |
7104 | | function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
7105 | | bytes32 m0;
7106 | | bytes32 m1;
7107 | | bytes32 m2;
7108 | | bytes32 m3;
7109 | | bytes32 m4;
7110 | | /// @solidity memory-safe-assembly
7111 | | assembly {
7112 | | m0 := mload(0x00)
7113 | | m1 := mload(0x20)
7114 | | m2 := mload(0x40)
7115 | | m3 := mload(0x60)
7116 | | m4 := mload(0x80)
7117 | | // Selector of `log(bool,uint256,uint256,uint256)`.
7118 | | mstore(0x00, 0x374bb4b2)
7119 | | mstore(0x20, p0)
7120 | | mstore(0x40, p1)
7121 | | mstore(0x60, p2)
7122 | | mstore(0x80, p3)
7123 | | }
7124 | | _sendLogPayload(0x1c, 0x84);
7125 | | /// @solidity memory-safe-assembly
7126 | | assembly {
7127 | | mstore(0x00, m0)
7128 | | mstore(0x20, m1)
7129 | | mstore(0x40, m2)
7130 | | mstore(0x60, m3)
7131 | | mstore(0x80, m4)
7132 | | }
7133 | | }
7134 | |
7135 | | function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
7136 | | bytes32 m0;
7137 | | bytes32 m1;
7138 | | bytes32 m2;
7139 | | bytes32 m3;
7140 | | bytes32 m4;
7141 | | bytes32 m5;
7142 | | bytes32 m6;
7143 | | /// @solidity memory-safe-assembly
7144 | | assembly {
7145 | | function writeString(pos, w) {
7146 | | let length := 0
7147 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7148 | | mstore(pos, length)
7149 | | let shift := sub(256, shl(3, length))
7150 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7151 | | }
7152 | | m0 := mload(0x00)
7153 | | m1 := mload(0x20)
7154 | | m2 := mload(0x40)
7155 | | m3 := mload(0x60)
7156 | | m4 := mload(0x80)
7157 | | m5 := mload(0xa0)
7158 | | m6 := mload(0xc0)
7159 | | // Selector of `log(bool,uint256,uint256,string)`.
7160 | | mstore(0x00, 0x8e69fb5d)
7161 | | mstore(0x20, p0)
7162 | | mstore(0x40, p1)
7163 | | mstore(0x60, p2)
7164 | | mstore(0x80, 0x80)
7165 | | writeString(0xa0, p3)
7166 | | }
7167 | | _sendLogPayload(0x1c, 0xc4);
7168 | | /// @solidity memory-safe-assembly
7169 | | assembly {
7170 | | mstore(0x00, m0)
7171 | | mstore(0x20, m1)
7172 | | mstore(0x40, m2)
7173 | | mstore(0x60, m3)
7174 | | mstore(0x80, m4)
7175 | | mstore(0xa0, m5)
7176 | | mstore(0xc0, m6)
7177 | | }
7178 | | }
7179 | |
7180 | | function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure {
7181 | | bytes32 m0;
7182 | | bytes32 m1;
7183 | | bytes32 m2;
7184 | | bytes32 m3;
7185 | | bytes32 m4;
7186 | | bytes32 m5;
7187 | | bytes32 m6;
7188 | | /// @solidity memory-safe-assembly
7189 | | assembly {
7190 | | function writeString(pos, w) {
7191 | | let length := 0
7192 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7193 | | mstore(pos, length)
7194 | | let shift := sub(256, shl(3, length))
7195 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7196 | | }
7197 | | m0 := mload(0x00)
7198 | | m1 := mload(0x20)
7199 | | m2 := mload(0x40)
7200 | | m3 := mload(0x60)
7201 | | m4 := mload(0x80)
7202 | | m5 := mload(0xa0)
7203 | | m6 := mload(0xc0)
7204 | | // Selector of `log(bool,uint256,string,address)`.
7205 | | mstore(0x00, 0xfedd1fff)
7206 | | mstore(0x20, p0)
7207 | | mstore(0x40, p1)
7208 | | mstore(0x60, 0x80)
7209 | | mstore(0x80, p3)
7210 | | writeString(0xa0, p2)
7211 | | }
7212 | | _sendLogPayload(0x1c, 0xc4);
7213 | | /// @solidity memory-safe-assembly
7214 | | assembly {
7215 | | mstore(0x00, m0)
7216 | | mstore(0x20, m1)
7217 | | mstore(0x40, m2)
7218 | | mstore(0x60, m3)
7219 | | mstore(0x80, m4)
7220 | | mstore(0xa0, m5)
7221 | | mstore(0xc0, m6)
7222 | | }
7223 | | }
7224 | |
7225 | | function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure {
7226 | | bytes32 m0;
7227 | | bytes32 m1;
7228 | | bytes32 m2;
7229 | | bytes32 m3;
7230 | | bytes32 m4;
7231 | | bytes32 m5;
7232 | | bytes32 m6;
7233 | | /// @solidity memory-safe-assembly
7234 | | assembly {
7235 | | function writeString(pos, w) {
7236 | | let length := 0
7237 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7238 | | mstore(pos, length)
7239 | | let shift := sub(256, shl(3, length))
7240 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7241 | | }
7242 | | m0 := mload(0x00)
7243 | | m1 := mload(0x20)
7244 | | m2 := mload(0x40)
7245 | | m3 := mload(0x60)
7246 | | m4 := mload(0x80)
7247 | | m5 := mload(0xa0)
7248 | | m6 := mload(0xc0)
7249 | | // Selector of `log(bool,uint256,string,bool)`.
7250 | | mstore(0x00, 0xe5e70b2b)
7251 | | mstore(0x20, p0)
7252 | | mstore(0x40, p1)
7253 | | mstore(0x60, 0x80)
7254 | | mstore(0x80, p3)
7255 | | writeString(0xa0, p2)
7256 | | }
7257 | | _sendLogPayload(0x1c, 0xc4);
7258 | | /// @solidity memory-safe-assembly
7259 | | assembly {
7260 | | mstore(0x00, m0)
7261 | | mstore(0x20, m1)
7262 | | mstore(0x40, m2)
7263 | | mstore(0x60, m3)
7264 | | mstore(0x80, m4)
7265 | | mstore(0xa0, m5)
7266 | | mstore(0xc0, m6)
7267 | | }
7268 | | }
7269 | |
7270 | | function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
7271 | | bytes32 m0;
7272 | | bytes32 m1;
7273 | | bytes32 m2;
7274 | | bytes32 m3;
7275 | | bytes32 m4;
7276 | | bytes32 m5;
7277 | | bytes32 m6;
7278 | | /// @solidity memory-safe-assembly
7279 | | assembly {
7280 | | function writeString(pos, w) {
7281 | | let length := 0
7282 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7283 | | mstore(pos, length)
7284 | | let shift := sub(256, shl(3, length))
7285 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7286 | | }
7287 | | m0 := mload(0x00)
7288 | | m1 := mload(0x20)
7289 | | m2 := mload(0x40)
7290 | | m3 := mload(0x60)
7291 | | m4 := mload(0x80)
7292 | | m5 := mload(0xa0)
7293 | | m6 := mload(0xc0)
7294 | | // Selector of `log(bool,uint256,string,uint256)`.
7295 | | mstore(0x00, 0x6a1199e2)
7296 | | mstore(0x20, p0)
7297 | | mstore(0x40, p1)
7298 | | mstore(0x60, 0x80)
7299 | | mstore(0x80, p3)
7300 | | writeString(0xa0, p2)
7301 | | }
7302 | | _sendLogPayload(0x1c, 0xc4);
7303 | | /// @solidity memory-safe-assembly
7304 | | assembly {
7305 | | mstore(0x00, m0)
7306 | | mstore(0x20, m1)
7307 | | mstore(0x40, m2)
7308 | | mstore(0x60, m3)
7309 | | mstore(0x80, m4)
7310 | | mstore(0xa0, m5)
7311 | | mstore(0xc0, m6)
7312 | | }
7313 | | }
7314 | |
7315 | | function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
7316 | | bytes32 m0;
7317 | | bytes32 m1;
7318 | | bytes32 m2;
7319 | | bytes32 m3;
7320 | | bytes32 m4;
7321 | | bytes32 m5;
7322 | | bytes32 m6;
7323 | | bytes32 m7;
7324 | | bytes32 m8;
7325 | | /// @solidity memory-safe-assembly
7326 | | assembly {
7327 | | function writeString(pos, w) {
7328 | | let length := 0
7329 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7330 | | mstore(pos, length)
7331 | | let shift := sub(256, shl(3, length))
7332 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7333 | | }
7334 | | m0 := mload(0x00)
7335 | | m1 := mload(0x20)
7336 | | m2 := mload(0x40)
7337 | | m3 := mload(0x60)
7338 | | m4 := mload(0x80)
7339 | | m5 := mload(0xa0)
7340 | | m6 := mload(0xc0)
7341 | | m7 := mload(0xe0)
7342 | | m8 := mload(0x100)
7343 | | // Selector of `log(bool,uint256,string,string)`.
7344 | | mstore(0x00, 0xf5bc2249)
7345 | | mstore(0x20, p0)
7346 | | mstore(0x40, p1)
7347 | | mstore(0x60, 0x80)
7348 | | mstore(0x80, 0xc0)
7349 | | writeString(0xa0, p2)
7350 | | writeString(0xe0, p3)
7351 | | }
7352 | | _sendLogPayload(0x1c, 0x104);
7353 | | /// @solidity memory-safe-assembly
7354 | | assembly {
7355 | | mstore(0x00, m0)
7356 | | mstore(0x20, m1)
7357 | | mstore(0x40, m2)
7358 | | mstore(0x60, m3)
7359 | | mstore(0x80, m4)
7360 | | mstore(0xa0, m5)
7361 | | mstore(0xc0, m6)
7362 | | mstore(0xe0, m7)
7363 | | mstore(0x100, m8)
7364 | | }
7365 | | }
7366 | |
7367 | | function log(bool p0, bytes32 p1, address p2, address p3) internal pure {
7368 | | bytes32 m0;
7369 | | bytes32 m1;
7370 | | bytes32 m2;
7371 | | bytes32 m3;
7372 | | bytes32 m4;
7373 | | bytes32 m5;
7374 | | bytes32 m6;
7375 | | /// @solidity memory-safe-assembly
7376 | | assembly {
7377 | | function writeString(pos, w) {
7378 | | let length := 0
7379 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7380 | | mstore(pos, length)
7381 | | let shift := sub(256, shl(3, length))
7382 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7383 | | }
7384 | | m0 := mload(0x00)
7385 | | m1 := mload(0x20)
7386 | | m2 := mload(0x40)
7387 | | m3 := mload(0x60)
7388 | | m4 := mload(0x80)
7389 | | m5 := mload(0xa0)
7390 | | m6 := mload(0xc0)
7391 | | // Selector of `log(bool,string,address,address)`.
7392 | | mstore(0x00, 0x2b2b18dc)
7393 | | mstore(0x20, p0)
7394 | | mstore(0x40, 0x80)
7395 | | mstore(0x60, p2)
7396 | | mstore(0x80, p3)
7397 | | writeString(0xa0, p1)
7398 | | }
7399 | | _sendLogPayload(0x1c, 0xc4);
7400 | | /// @solidity memory-safe-assembly
7401 | | assembly {
7402 | | mstore(0x00, m0)
7403 | | mstore(0x20, m1)
7404 | | mstore(0x40, m2)
7405 | | mstore(0x60, m3)
7406 | | mstore(0x80, m4)
7407 | | mstore(0xa0, m5)
7408 | | mstore(0xc0, m6)
7409 | | }
7410 | | }
7411 | |
7412 | | function log(bool p0, bytes32 p1, address p2, bool p3) internal pure {
7413 | | bytes32 m0;
7414 | | bytes32 m1;
7415 | | bytes32 m2;
7416 | | bytes32 m3;
7417 | | bytes32 m4;
7418 | | bytes32 m5;
7419 | | bytes32 m6;
7420 | | /// @solidity memory-safe-assembly
7421 | | assembly {
7422 | | function writeString(pos, w) {
7423 | | let length := 0
7424 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7425 | | mstore(pos, length)
7426 | | let shift := sub(256, shl(3, length))
7427 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7428 | | }
7429 | | m0 := mload(0x00)
7430 | | m1 := mload(0x20)
7431 | | m2 := mload(0x40)
7432 | | m3 := mload(0x60)
7433 | | m4 := mload(0x80)
7434 | | m5 := mload(0xa0)
7435 | | m6 := mload(0xc0)
7436 | | // Selector of `log(bool,string,address,bool)`.
7437 | | mstore(0x00, 0x6dd434ca)
7438 | | mstore(0x20, p0)
7439 | | mstore(0x40, 0x80)
7440 | | mstore(0x60, p2)
7441 | | mstore(0x80, p3)
7442 | | writeString(0xa0, p1)
7443 | | }
7444 | | _sendLogPayload(0x1c, 0xc4);
7445 | | /// @solidity memory-safe-assembly
7446 | | assembly {
7447 | | mstore(0x00, m0)
7448 | | mstore(0x20, m1)
7449 | | mstore(0x40, m2)
7450 | | mstore(0x60, m3)
7451 | | mstore(0x80, m4)
7452 | | mstore(0xa0, m5)
7453 | | mstore(0xc0, m6)
7454 | | }
7455 | | }
7456 | |
7457 | | function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure {
7458 | | bytes32 m0;
7459 | | bytes32 m1;
7460 | | bytes32 m2;
7461 | | bytes32 m3;
7462 | | bytes32 m4;
7463 | | bytes32 m5;
7464 | | bytes32 m6;
7465 | | /// @solidity memory-safe-assembly
7466 | | assembly {
7467 | | function writeString(pos, w) {
7468 | | let length := 0
7469 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7470 | | mstore(pos, length)
7471 | | let shift := sub(256, shl(3, length))
7472 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7473 | | }
7474 | | m0 := mload(0x00)
7475 | | m1 := mload(0x20)
7476 | | m2 := mload(0x40)
7477 | | m3 := mload(0x60)
7478 | | m4 := mload(0x80)
7479 | | m5 := mload(0xa0)
7480 | | m6 := mload(0xc0)
7481 | | // Selector of `log(bool,string,address,uint256)`.
7482 | | mstore(0x00, 0xa5cada94)
7483 | | mstore(0x20, p0)
7484 | | mstore(0x40, 0x80)
7485 | | mstore(0x60, p2)
7486 | | mstore(0x80, p3)
7487 | | writeString(0xa0, p1)
7488 | | }
7489 | | _sendLogPayload(0x1c, 0xc4);
7490 | | /// @solidity memory-safe-assembly
7491 | | assembly {
7492 | | mstore(0x00, m0)
7493 | | mstore(0x20, m1)
7494 | | mstore(0x40, m2)
7495 | | mstore(0x60, m3)
7496 | | mstore(0x80, m4)
7497 | | mstore(0xa0, m5)
7498 | | mstore(0xc0, m6)
7499 | | }
7500 | | }
7501 | |
7502 | | function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure {
7503 | | bytes32 m0;
7504 | | bytes32 m1;
7505 | | bytes32 m2;
7506 | | bytes32 m3;
7507 | | bytes32 m4;
7508 | | bytes32 m5;
7509 | | bytes32 m6;
7510 | | bytes32 m7;
7511 | | bytes32 m8;
7512 | | /// @solidity memory-safe-assembly
7513 | | assembly {
7514 | | function writeString(pos, w) {
7515 | | let length := 0
7516 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7517 | | mstore(pos, length)
7518 | | let shift := sub(256, shl(3, length))
7519 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7520 | | }
7521 | | m0 := mload(0x00)
7522 | | m1 := mload(0x20)
7523 | | m2 := mload(0x40)
7524 | | m3 := mload(0x60)
7525 | | m4 := mload(0x80)
7526 | | m5 := mload(0xa0)
7527 | | m6 := mload(0xc0)
7528 | | m7 := mload(0xe0)
7529 | | m8 := mload(0x100)
7530 | | // Selector of `log(bool,string,address,string)`.
7531 | | mstore(0x00, 0x12d6c788)
7532 | | mstore(0x20, p0)
7533 | | mstore(0x40, 0x80)
7534 | | mstore(0x60, p2)
7535 | | mstore(0x80, 0xc0)
7536 | | writeString(0xa0, p1)
7537 | | writeString(0xe0, p3)
7538 | | }
7539 | | _sendLogPayload(0x1c, 0x104);
7540 | | /// @solidity memory-safe-assembly
7541 | | assembly {
7542 | | mstore(0x00, m0)
7543 | | mstore(0x20, m1)
7544 | | mstore(0x40, m2)
7545 | | mstore(0x60, m3)
7546 | | mstore(0x80, m4)
7547 | | mstore(0xa0, m5)
7548 | | mstore(0xc0, m6)
7549 | | mstore(0xe0, m7)
7550 | | mstore(0x100, m8)
7551 | | }
7552 | | }
7553 | |
7554 | | function log(bool p0, bytes32 p1, bool p2, address p3) internal pure {
7555 | | bytes32 m0;
7556 | | bytes32 m1;
7557 | | bytes32 m2;
7558 | | bytes32 m3;
7559 | | bytes32 m4;
7560 | | bytes32 m5;
7561 | | bytes32 m6;
7562 | | /// @solidity memory-safe-assembly
7563 | | assembly {
7564 | | function writeString(pos, w) {
7565 | | let length := 0
7566 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7567 | | mstore(pos, length)
7568 | | let shift := sub(256, shl(3, length))
7569 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7570 | | }
7571 | | m0 := mload(0x00)
7572 | | m1 := mload(0x20)
7573 | | m2 := mload(0x40)
7574 | | m3 := mload(0x60)
7575 | | m4 := mload(0x80)
7576 | | m5 := mload(0xa0)
7577 | | m6 := mload(0xc0)
7578 | | // Selector of `log(bool,string,bool,address)`.
7579 | | mstore(0x00, 0x538e06ab)
7580 | | mstore(0x20, p0)
7581 | | mstore(0x40, 0x80)
7582 | | mstore(0x60, p2)
7583 | | mstore(0x80, p3)
7584 | | writeString(0xa0, p1)
7585 | | }
7586 | | _sendLogPayload(0x1c, 0xc4);
7587 | | /// @solidity memory-safe-assembly
7588 | | assembly {
7589 | | mstore(0x00, m0)
7590 | | mstore(0x20, m1)
7591 | | mstore(0x40, m2)
7592 | | mstore(0x60, m3)
7593 | | mstore(0x80, m4)
7594 | | mstore(0xa0, m5)
7595 | | mstore(0xc0, m6)
7596 | | }
7597 | | }
7598 | |
7599 | | function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure {
7600 | | bytes32 m0;
7601 | | bytes32 m1;
7602 | | bytes32 m2;
7603 | | bytes32 m3;
7604 | | bytes32 m4;
7605 | | bytes32 m5;
7606 | | bytes32 m6;
7607 | | /// @solidity memory-safe-assembly
7608 | | assembly {
7609 | | function writeString(pos, w) {
7610 | | let length := 0
7611 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7612 | | mstore(pos, length)
7613 | | let shift := sub(256, shl(3, length))
7614 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7615 | | }
7616 | | m0 := mload(0x00)
7617 | | m1 := mload(0x20)
7618 | | m2 := mload(0x40)
7619 | | m3 := mload(0x60)
7620 | | m4 := mload(0x80)
7621 | | m5 := mload(0xa0)
7622 | | m6 := mload(0xc0)
7623 | | // Selector of `log(bool,string,bool,bool)`.
7624 | | mstore(0x00, 0xdc5e935b)
7625 | | mstore(0x20, p0)
7626 | | mstore(0x40, 0x80)
7627 | | mstore(0x60, p2)
7628 | | mstore(0x80, p3)
7629 | | writeString(0xa0, p1)
7630 | | }
7631 | | _sendLogPayload(0x1c, 0xc4);
7632 | | /// @solidity memory-safe-assembly
7633 | | assembly {
7634 | | mstore(0x00, m0)
7635 | | mstore(0x20, m1)
7636 | | mstore(0x40, m2)
7637 | | mstore(0x60, m3)
7638 | | mstore(0x80, m4)
7639 | | mstore(0xa0, m5)
7640 | | mstore(0xc0, m6)
7641 | | }
7642 | | }
7643 | |
7644 | | function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure {
7645 | | bytes32 m0;
7646 | | bytes32 m1;
7647 | | bytes32 m2;
7648 | | bytes32 m3;
7649 | | bytes32 m4;
7650 | | bytes32 m5;
7651 | | bytes32 m6;
7652 | | /// @solidity memory-safe-assembly
7653 | | assembly {
7654 | | function writeString(pos, w) {
7655 | | let length := 0
7656 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7657 | | mstore(pos, length)
7658 | | let shift := sub(256, shl(3, length))
7659 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7660 | | }
7661 | | m0 := mload(0x00)
7662 | | m1 := mload(0x20)
7663 | | m2 := mload(0x40)
7664 | | m3 := mload(0x60)
7665 | | m4 := mload(0x80)
7666 | | m5 := mload(0xa0)
7667 | | m6 := mload(0xc0)
7668 | | // Selector of `log(bool,string,bool,uint256)`.
7669 | | mstore(0x00, 0x1606a393)
7670 | | mstore(0x20, p0)
7671 | | mstore(0x40, 0x80)
7672 | | mstore(0x60, p2)
7673 | | mstore(0x80, p3)
7674 | | writeString(0xa0, p1)
7675 | | }
7676 | | _sendLogPayload(0x1c, 0xc4);
7677 | | /// @solidity memory-safe-assembly
7678 | | assembly {
7679 | | mstore(0x00, m0)
7680 | | mstore(0x20, m1)
7681 | | mstore(0x40, m2)
7682 | | mstore(0x60, m3)
7683 | | mstore(0x80, m4)
7684 | | mstore(0xa0, m5)
7685 | | mstore(0xc0, m6)
7686 | | }
7687 | | }
7688 | |
7689 | | function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
7690 | | bytes32 m0;
7691 | | bytes32 m1;
7692 | | bytes32 m2;
7693 | | bytes32 m3;
7694 | | bytes32 m4;
7695 | | bytes32 m5;
7696 | | bytes32 m6;
7697 | | bytes32 m7;
7698 | | bytes32 m8;
7699 | | /// @solidity memory-safe-assembly
7700 | | assembly {
7701 | | function writeString(pos, w) {
7702 | | let length := 0
7703 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7704 | | mstore(pos, length)
7705 | | let shift := sub(256, shl(3, length))
7706 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7707 | | }
7708 | | m0 := mload(0x00)
7709 | | m1 := mload(0x20)
7710 | | m2 := mload(0x40)
7711 | | m3 := mload(0x60)
7712 | | m4 := mload(0x80)
7713 | | m5 := mload(0xa0)
7714 | | m6 := mload(0xc0)
7715 | | m7 := mload(0xe0)
7716 | | m8 := mload(0x100)
7717 | | // Selector of `log(bool,string,bool,string)`.
7718 | | mstore(0x00, 0x483d0416)
7719 | | mstore(0x20, p0)
7720 | | mstore(0x40, 0x80)
7721 | | mstore(0x60, p2)
7722 | | mstore(0x80, 0xc0)
7723 | | writeString(0xa0, p1)
7724 | | writeString(0xe0, p3)
7725 | | }
7726 | | _sendLogPayload(0x1c, 0x104);
7727 | | /// @solidity memory-safe-assembly
7728 | | assembly {
7729 | | mstore(0x00, m0)
7730 | | mstore(0x20, m1)
7731 | | mstore(0x40, m2)
7732 | | mstore(0x60, m3)
7733 | | mstore(0x80, m4)
7734 | | mstore(0xa0, m5)
7735 | | mstore(0xc0, m6)
7736 | | mstore(0xe0, m7)
7737 | | mstore(0x100, m8)
7738 | | }
7739 | | }
7740 | |
7741 | | function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure {
7742 | | bytes32 m0;
7743 | | bytes32 m1;
7744 | | bytes32 m2;
7745 | | bytes32 m3;
7746 | | bytes32 m4;
7747 | | bytes32 m5;
7748 | | bytes32 m6;
7749 | | /// @solidity memory-safe-assembly
7750 | | assembly {
7751 | | function writeString(pos, w) {
7752 | | let length := 0
7753 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7754 | | mstore(pos, length)
7755 | | let shift := sub(256, shl(3, length))
7756 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7757 | | }
7758 | | m0 := mload(0x00)
7759 | | m1 := mload(0x20)
7760 | | m2 := mload(0x40)
7761 | | m3 := mload(0x60)
7762 | | m4 := mload(0x80)
7763 | | m5 := mload(0xa0)
7764 | | m6 := mload(0xc0)
7765 | | // Selector of `log(bool,string,uint256,address)`.
7766 | | mstore(0x00, 0x1596a1ce)
7767 | | mstore(0x20, p0)
7768 | | mstore(0x40, 0x80)
7769 | | mstore(0x60, p2)
7770 | | mstore(0x80, p3)
7771 | | writeString(0xa0, p1)
7772 | | }
7773 | | _sendLogPayload(0x1c, 0xc4);
7774 | | /// @solidity memory-safe-assembly
7775 | | assembly {
7776 | | mstore(0x00, m0)
7777 | | mstore(0x20, m1)
7778 | | mstore(0x40, m2)
7779 | | mstore(0x60, m3)
7780 | | mstore(0x80, m4)
7781 | | mstore(0xa0, m5)
7782 | | mstore(0xc0, m6)
7783 | | }
7784 | | }
7785 | |
7786 | | function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure {
7787 | | bytes32 m0;
7788 | | bytes32 m1;
7789 | | bytes32 m2;
7790 | | bytes32 m3;
7791 | | bytes32 m4;
7792 | | bytes32 m5;
7793 | | bytes32 m6;
7794 | | /// @solidity memory-safe-assembly
7795 | | assembly {
7796 | | function writeString(pos, w) {
7797 | | let length := 0
7798 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7799 | | mstore(pos, length)
7800 | | let shift := sub(256, shl(3, length))
7801 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7802 | | }
7803 | | m0 := mload(0x00)
7804 | | m1 := mload(0x20)
7805 | | m2 := mload(0x40)
7806 | | m3 := mload(0x60)
7807 | | m4 := mload(0x80)
7808 | | m5 := mload(0xa0)
7809 | | m6 := mload(0xc0)
7810 | | // Selector of `log(bool,string,uint256,bool)`.
7811 | | mstore(0x00, 0x6b0e5d53)
7812 | | mstore(0x20, p0)
7813 | | mstore(0x40, 0x80)
7814 | | mstore(0x60, p2)
7815 | | mstore(0x80, p3)
7816 | | writeString(0xa0, p1)
7817 | | }
7818 | | _sendLogPayload(0x1c, 0xc4);
7819 | | /// @solidity memory-safe-assembly
7820 | | assembly {
7821 | | mstore(0x00, m0)
7822 | | mstore(0x20, m1)
7823 | | mstore(0x40, m2)
7824 | | mstore(0x60, m3)
7825 | | mstore(0x80, m4)
7826 | | mstore(0xa0, m5)
7827 | | mstore(0xc0, m6)
7828 | | }
7829 | | }
7830 | |
7831 | | function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
7832 | | bytes32 m0;
7833 | | bytes32 m1;
7834 | | bytes32 m2;
7835 | | bytes32 m3;
7836 | | bytes32 m4;
7837 | | bytes32 m5;
7838 | | bytes32 m6;
7839 | | /// @solidity memory-safe-assembly
7840 | | assembly {
7841 | | function writeString(pos, w) {
7842 | | let length := 0
7843 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7844 | | mstore(pos, length)
7845 | | let shift := sub(256, shl(3, length))
7846 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7847 | | }
7848 | | m0 := mload(0x00)
7849 | | m1 := mload(0x20)
7850 | | m2 := mload(0x40)
7851 | | m3 := mload(0x60)
7852 | | m4 := mload(0x80)
7853 | | m5 := mload(0xa0)
7854 | | m6 := mload(0xc0)
7855 | | // Selector of `log(bool,string,uint256,uint256)`.
7856 | | mstore(0x00, 0x28863fcb)
7857 | | mstore(0x20, p0)
7858 | | mstore(0x40, 0x80)
7859 | | mstore(0x60, p2)
7860 | | mstore(0x80, p3)
7861 | | writeString(0xa0, p1)
7862 | | }
7863 | | _sendLogPayload(0x1c, 0xc4);
7864 | | /// @solidity memory-safe-assembly
7865 | | assembly {
7866 | | mstore(0x00, m0)
7867 | | mstore(0x20, m1)
7868 | | mstore(0x40, m2)
7869 | | mstore(0x60, m3)
7870 | | mstore(0x80, m4)
7871 | | mstore(0xa0, m5)
7872 | | mstore(0xc0, m6)
7873 | | }
7874 | | }
7875 | |
7876 | | function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
7877 | | bytes32 m0;
7878 | | bytes32 m1;
7879 | | bytes32 m2;
7880 | | bytes32 m3;
7881 | | bytes32 m4;
7882 | | bytes32 m5;
7883 | | bytes32 m6;
7884 | | bytes32 m7;
7885 | | bytes32 m8;
7886 | | /// @solidity memory-safe-assembly
7887 | | assembly {
7888 | | function writeString(pos, w) {
7889 | | let length := 0
7890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7891 | | mstore(pos, length)
7892 | | let shift := sub(256, shl(3, length))
7893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7894 | | }
7895 | | m0 := mload(0x00)
7896 | | m1 := mload(0x20)
7897 | | m2 := mload(0x40)
7898 | | m3 := mload(0x60)
7899 | | m4 := mload(0x80)
7900 | | m5 := mload(0xa0)
7901 | | m6 := mload(0xc0)
7902 | | m7 := mload(0xe0)
7903 | | m8 := mload(0x100)
7904 | | // Selector of `log(bool,string,uint256,string)`.
7905 | | mstore(0x00, 0x1ad96de6)
7906 | | mstore(0x20, p0)
7907 | | mstore(0x40, 0x80)
7908 | | mstore(0x60, p2)
7909 | | mstore(0x80, 0xc0)
7910 | | writeString(0xa0, p1)
7911 | | writeString(0xe0, p3)
7912 | | }
7913 | | _sendLogPayload(0x1c, 0x104);
7914 | | /// @solidity memory-safe-assembly
7915 | | assembly {
7916 | | mstore(0x00, m0)
7917 | | mstore(0x20, m1)
7918 | | mstore(0x40, m2)
7919 | | mstore(0x60, m3)
7920 | | mstore(0x80, m4)
7921 | | mstore(0xa0, m5)
7922 | | mstore(0xc0, m6)
7923 | | mstore(0xe0, m7)
7924 | | mstore(0x100, m8)
7925 | | }
7926 | | }
7927 | |
7928 | | function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure {
7929 | | bytes32 m0;
7930 | | bytes32 m1;
7931 | | bytes32 m2;
7932 | | bytes32 m3;
7933 | | bytes32 m4;
7934 | | bytes32 m5;
7935 | | bytes32 m6;
7936 | | bytes32 m7;
7937 | | bytes32 m8;
7938 | | /// @solidity memory-safe-assembly
7939 | | assembly {
7940 | | function writeString(pos, w) {
7941 | | let length := 0
7942 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7943 | | mstore(pos, length)
7944 | | let shift := sub(256, shl(3, length))
7945 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7946 | | }
7947 | | m0 := mload(0x00)
7948 | | m1 := mload(0x20)
7949 | | m2 := mload(0x40)
7950 | | m3 := mload(0x60)
7951 | | m4 := mload(0x80)
7952 | | m5 := mload(0xa0)
7953 | | m6 := mload(0xc0)
7954 | | m7 := mload(0xe0)
7955 | | m8 := mload(0x100)
7956 | | // Selector of `log(bool,string,string,address)`.
7957 | | mstore(0x00, 0x97d394d8)
7958 | | mstore(0x20, p0)
7959 | | mstore(0x40, 0x80)
7960 | | mstore(0x60, 0xc0)
7961 | | mstore(0x80, p3)
7962 | | writeString(0xa0, p1)
7963 | | writeString(0xe0, p2)
7964 | | }
7965 | | _sendLogPayload(0x1c, 0x104);
7966 | | /// @solidity memory-safe-assembly
7967 | | assembly {
7968 | | mstore(0x00, m0)
7969 | | mstore(0x20, m1)
7970 | | mstore(0x40, m2)
7971 | | mstore(0x60, m3)
7972 | | mstore(0x80, m4)
7973 | | mstore(0xa0, m5)
7974 | | mstore(0xc0, m6)
7975 | | mstore(0xe0, m7)
7976 | | mstore(0x100, m8)
7977 | | }
7978 | | }
7979 | |
7980 | | function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
7981 | | bytes32 m0;
7982 | | bytes32 m1;
7983 | | bytes32 m2;
7984 | | bytes32 m3;
7985 | | bytes32 m4;
7986 | | bytes32 m5;
7987 | | bytes32 m6;
7988 | | bytes32 m7;
7989 | | bytes32 m8;
7990 | | /// @solidity memory-safe-assembly
7991 | | assembly {
7992 | | function writeString(pos, w) {
7993 | | let length := 0
7994 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7995 | | mstore(pos, length)
7996 | | let shift := sub(256, shl(3, length))
7997 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7998 | | }
7999 | | m0 := mload(0x00)
8000 | | m1 := mload(0x20)
8001 | | m2 := mload(0x40)
8002 | | m3 := mload(0x60)
8003 | | m4 := mload(0x80)
8004 | | m5 := mload(0xa0)
8005 | | m6 := mload(0xc0)
8006 | | m7 := mload(0xe0)
8007 | | m8 := mload(0x100)
8008 | | // Selector of `log(bool,string,string,bool)`.
8009 | | mstore(0x00, 0x1e4b87e5)
8010 | | mstore(0x20, p0)
8011 | | mstore(0x40, 0x80)
8012 | | mstore(0x60, 0xc0)
8013 | | mstore(0x80, p3)
8014 | | writeString(0xa0, p1)
8015 | | writeString(0xe0, p2)
8016 | | }
8017 | | _sendLogPayload(0x1c, 0x104);
8018 | | /// @solidity memory-safe-assembly
8019 | | assembly {
8020 | | mstore(0x00, m0)
8021 | | mstore(0x20, m1)
8022 | | mstore(0x40, m2)
8023 | | mstore(0x60, m3)
8024 | | mstore(0x80, m4)
8025 | | mstore(0xa0, m5)
8026 | | mstore(0xc0, m6)
8027 | | mstore(0xe0, m7)
8028 | | mstore(0x100, m8)
8029 | | }
8030 | | }
8031 | |
8032 | | function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
8033 | | bytes32 m0;
8034 | | bytes32 m1;
8035 | | bytes32 m2;
8036 | | bytes32 m3;
8037 | | bytes32 m4;
8038 | | bytes32 m5;
8039 | | bytes32 m6;
8040 | | bytes32 m7;
8041 | | bytes32 m8;
8042 | | /// @solidity memory-safe-assembly
8043 | | assembly {
8044 | | function writeString(pos, w) {
8045 | | let length := 0
8046 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8047 | | mstore(pos, length)
8048 | | let shift := sub(256, shl(3, length))
8049 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8050 | | }
8051 | | m0 := mload(0x00)
8052 | | m1 := mload(0x20)
8053 | | m2 := mload(0x40)
8054 | | m3 := mload(0x60)
8055 | | m4 := mload(0x80)
8056 | | m5 := mload(0xa0)
8057 | | m6 := mload(0xc0)
8058 | | m7 := mload(0xe0)
8059 | | m8 := mload(0x100)
8060 | | // Selector of `log(bool,string,string,uint256)`.
8061 | | mstore(0x00, 0x7be0c3eb)
8062 | | mstore(0x20, p0)
8063 | | mstore(0x40, 0x80)
8064 | | mstore(0x60, 0xc0)
8065 | | mstore(0x80, p3)
8066 | | writeString(0xa0, p1)
8067 | | writeString(0xe0, p2)
8068 | | }
8069 | | _sendLogPayload(0x1c, 0x104);
8070 | | /// @solidity memory-safe-assembly
8071 | | assembly {
8072 | | mstore(0x00, m0)
8073 | | mstore(0x20, m1)
8074 | | mstore(0x40, m2)
8075 | | mstore(0x60, m3)
8076 | | mstore(0x80, m4)
8077 | | mstore(0xa0, m5)
8078 | | mstore(0xc0, m6)
8079 | | mstore(0xe0, m7)
8080 | | mstore(0x100, m8)
8081 | | }
8082 | | }
8083 | |
8084 | | function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
8085 | | bytes32 m0;
8086 | | bytes32 m1;
8087 | | bytes32 m2;
8088 | | bytes32 m3;
8089 | | bytes32 m4;
8090 | | bytes32 m5;
8091 | | bytes32 m6;
8092 | | bytes32 m7;
8093 | | bytes32 m8;
8094 | | bytes32 m9;
8095 | | bytes32 m10;
8096 | | /// @solidity memory-safe-assembly
8097 | | assembly {
8098 | | function writeString(pos, w) {
8099 | | let length := 0
8100 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8101 | | mstore(pos, length)
8102 | | let shift := sub(256, shl(3, length))
8103 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8104 | | }
8105 | | m0 := mload(0x00)
8106 | | m1 := mload(0x20)
8107 | | m2 := mload(0x40)
8108 | | m3 := mload(0x60)
8109 | | m4 := mload(0x80)
8110 | | m5 := mload(0xa0)
8111 | | m6 := mload(0xc0)
8112 | | m7 := mload(0xe0)
8113 | | m8 := mload(0x100)
8114 | | m9 := mload(0x120)
8115 | | m10 := mload(0x140)
8116 | | // Selector of `log(bool,string,string,string)`.
8117 | | mstore(0x00, 0x1762e32a)
8118 | | mstore(0x20, p0)
8119 | | mstore(0x40, 0x80)
8120 | | mstore(0x60, 0xc0)
8121 | | mstore(0x80, 0x100)
8122 | | writeString(0xa0, p1)
8123 | | writeString(0xe0, p2)
8124 | | writeString(0x120, p3)
8125 | | }
8126 | | _sendLogPayload(0x1c, 0x144);
8127 | | /// @solidity memory-safe-assembly
8128 | | assembly {
8129 | | mstore(0x00, m0)
8130 | | mstore(0x20, m1)
8131 | | mstore(0x40, m2)
8132 | | mstore(0x60, m3)
8133 | | mstore(0x80, m4)
8134 | | mstore(0xa0, m5)
8135 | | mstore(0xc0, m6)
8136 | | mstore(0xe0, m7)
8137 | | mstore(0x100, m8)
8138 | | mstore(0x120, m9)
8139 | | mstore(0x140, m10)
8140 | | }
8141 | | }
8142 | |
8143 | | function log(uint256 p0, address p1, address p2, address p3) internal pure {
8144 | | bytes32 m0;
8145 | | bytes32 m1;
8146 | | bytes32 m2;
8147 | | bytes32 m3;
8148 | | bytes32 m4;
8149 | | /// @solidity memory-safe-assembly
8150 | | assembly {
8151 | | m0 := mload(0x00)
8152 | | m1 := mload(0x20)
8153 | | m2 := mload(0x40)
8154 | | m3 := mload(0x60)
8155 | | m4 := mload(0x80)
8156 | | // Selector of `log(uint256,address,address,address)`.
8157 | | mstore(0x00, 0x2488b414)
8158 | | mstore(0x20, p0)
8159 | | mstore(0x40, p1)
8160 | | mstore(0x60, p2)
8161 | | mstore(0x80, p3)
8162 | | }
8163 | | _sendLogPayload(0x1c, 0x84);
8164 | | /// @solidity memory-safe-assembly
8165 | | assembly {
8166 | | mstore(0x00, m0)
8167 | | mstore(0x20, m1)
8168 | | mstore(0x40, m2)
8169 | | mstore(0x60, m3)
8170 | | mstore(0x80, m4)
8171 | | }
8172 | | }
8173 | |
8174 | | function log(uint256 p0, address p1, address p2, bool p3) internal pure {
8175 | | bytes32 m0;
8176 | | bytes32 m1;
8177 | | bytes32 m2;
8178 | | bytes32 m3;
8179 | | bytes32 m4;
8180 | | /// @solidity memory-safe-assembly
8181 | | assembly {
8182 | | m0 := mload(0x00)
8183 | | m1 := mload(0x20)
8184 | | m2 := mload(0x40)
8185 | | m3 := mload(0x60)
8186 | | m4 := mload(0x80)
8187 | | // Selector of `log(uint256,address,address,bool)`.
8188 | | mstore(0x00, 0x091ffaf5)
8189 | | mstore(0x20, p0)
8190 | | mstore(0x40, p1)
8191 | | mstore(0x60, p2)
8192 | | mstore(0x80, p3)
8193 | | }
8194 | | _sendLogPayload(0x1c, 0x84);
8195 | | /// @solidity memory-safe-assembly
8196 | | assembly {
8197 | | mstore(0x00, m0)
8198 | | mstore(0x20, m1)
8199 | | mstore(0x40, m2)
8200 | | mstore(0x60, m3)
8201 | | mstore(0x80, m4)
8202 | | }
8203 | | }
8204 | |
8205 | | function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
8206 | | bytes32 m0;
8207 | | bytes32 m1;
8208 | | bytes32 m2;
8209 | | bytes32 m3;
8210 | | bytes32 m4;
8211 | | /// @solidity memory-safe-assembly
8212 | | assembly {
8213 | | m0 := mload(0x00)
8214 | | m1 := mload(0x20)
8215 | | m2 := mload(0x40)
8216 | | m3 := mload(0x60)
8217 | | m4 := mload(0x80)
8218 | | // Selector of `log(uint256,address,address,uint256)`.
8219 | | mstore(0x00, 0x736efbb6)
8220 | | mstore(0x20, p0)
8221 | | mstore(0x40, p1)
8222 | | mstore(0x60, p2)
8223 | | mstore(0x80, p3)
8224 | | }
8225 | | _sendLogPayload(0x1c, 0x84);
8226 | | /// @solidity memory-safe-assembly
8227 | | assembly {
8228 | | mstore(0x00, m0)
8229 | | mstore(0x20, m1)
8230 | | mstore(0x40, m2)
8231 | | mstore(0x60, m3)
8232 | | mstore(0x80, m4)
8233 | | }
8234 | | }
8235 | |
8236 | | function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure {
8237 | | bytes32 m0;
8238 | | bytes32 m1;
8239 | | bytes32 m2;
8240 | | bytes32 m3;
8241 | | bytes32 m4;
8242 | | bytes32 m5;
8243 | | bytes32 m6;
8244 | | /// @solidity memory-safe-assembly
8245 | | assembly {
8246 | | function writeString(pos, w) {
8247 | | let length := 0
8248 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8249 | | mstore(pos, length)
8250 | | let shift := sub(256, shl(3, length))
8251 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8252 | | }
8253 | | m0 := mload(0x00)
8254 | | m1 := mload(0x20)
8255 | | m2 := mload(0x40)
8256 | | m3 := mload(0x60)
8257 | | m4 := mload(0x80)
8258 | | m5 := mload(0xa0)
8259 | | m6 := mload(0xc0)
8260 | | // Selector of `log(uint256,address,address,string)`.
8261 | | mstore(0x00, 0x031c6f73)
8262 | | mstore(0x20, p0)
8263 | | mstore(0x40, p1)
8264 | | mstore(0x60, p2)
8265 | | mstore(0x80, 0x80)
8266 | | writeString(0xa0, p3)
8267 | | }
8268 | | _sendLogPayload(0x1c, 0xc4);
8269 | | /// @solidity memory-safe-assembly
8270 | | assembly {
8271 | | mstore(0x00, m0)
8272 | | mstore(0x20, m1)
8273 | | mstore(0x40, m2)
8274 | | mstore(0x60, m3)
8275 | | mstore(0x80, m4)
8276 | | mstore(0xa0, m5)
8277 | | mstore(0xc0, m6)
8278 | | }
8279 | | }
8280 | |
8281 | | function log(uint256 p0, address p1, bool p2, address p3) internal pure {
8282 | | bytes32 m0;
8283 | | bytes32 m1;
8284 | | bytes32 m2;
8285 | | bytes32 m3;
8286 | | bytes32 m4;
8287 | | /// @solidity memory-safe-assembly
8288 | | assembly {
8289 | | m0 := mload(0x00)
8290 | | m1 := mload(0x20)
8291 | | m2 := mload(0x40)
8292 | | m3 := mload(0x60)
8293 | | m4 := mload(0x80)
8294 | | // Selector of `log(uint256,address,bool,address)`.
8295 | | mstore(0x00, 0xef72c513)
8296 | | mstore(0x20, p0)
8297 | | mstore(0x40, p1)
8298 | | mstore(0x60, p2)
8299 | | mstore(0x80, p3)
8300 | | }
8301 | | _sendLogPayload(0x1c, 0x84);
8302 | | /// @solidity memory-safe-assembly
8303 | | assembly {
8304 | | mstore(0x00, m0)
8305 | | mstore(0x20, m1)
8306 | | mstore(0x40, m2)
8307 | | mstore(0x60, m3)
8308 | | mstore(0x80, m4)
8309 | | }
8310 | | }
8311 | |
8312 | | function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
8313 | | bytes32 m0;
8314 | | bytes32 m1;
8315 | | bytes32 m2;
8316 | | bytes32 m3;
8317 | | bytes32 m4;
8318 | | /// @solidity memory-safe-assembly
8319 | | assembly {
8320 | | m0 := mload(0x00)
8321 | | m1 := mload(0x20)
8322 | | m2 := mload(0x40)
8323 | | m3 := mload(0x60)
8324 | | m4 := mload(0x80)
8325 | | // Selector of `log(uint256,address,bool,bool)`.
8326 | | mstore(0x00, 0xe351140f)
8327 | | mstore(0x20, p0)
8328 | | mstore(0x40, p1)
8329 | | mstore(0x60, p2)
8330 | | mstore(0x80, p3)
8331 | | }
8332 | | _sendLogPayload(0x1c, 0x84);
8333 | | /// @solidity memory-safe-assembly
8334 | | assembly {
8335 | | mstore(0x00, m0)
8336 | | mstore(0x20, m1)
8337 | | mstore(0x40, m2)
8338 | | mstore(0x60, m3)
8339 | | mstore(0x80, m4)
8340 | | }
8341 | | }
8342 | |
8343 | | function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
8344 | | bytes32 m0;
8345 | | bytes32 m1;
8346 | | bytes32 m2;
8347 | | bytes32 m3;
8348 | | bytes32 m4;
8349 | | /// @solidity memory-safe-assembly
8350 | | assembly {
8351 | | m0 := mload(0x00)
8352 | | m1 := mload(0x20)
8353 | | m2 := mload(0x40)
8354 | | m3 := mload(0x60)
8355 | | m4 := mload(0x80)
8356 | | // Selector of `log(uint256,address,bool,uint256)`.
8357 | | mstore(0x00, 0x5abd992a)
8358 | | mstore(0x20, p0)
8359 | | mstore(0x40, p1)
8360 | | mstore(0x60, p2)
8361 | | mstore(0x80, p3)
8362 | | }
8363 | | _sendLogPayload(0x1c, 0x84);
8364 | | /// @solidity memory-safe-assembly
8365 | | assembly {
8366 | | mstore(0x00, m0)
8367 | | mstore(0x20, m1)
8368 | | mstore(0x40, m2)
8369 | | mstore(0x60, m3)
8370 | | mstore(0x80, m4)
8371 | | }
8372 | | }
8373 | |
8374 | | function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure {
8375 | | bytes32 m0;
8376 | | bytes32 m1;
8377 | | bytes32 m2;
8378 | | bytes32 m3;
8379 | | bytes32 m4;
8380 | | bytes32 m5;
8381 | | bytes32 m6;
8382 | | /// @solidity memory-safe-assembly
8383 | | assembly {
8384 | | function writeString(pos, w) {
8385 | | let length := 0
8386 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8387 | | mstore(pos, length)
8388 | | let shift := sub(256, shl(3, length))
8389 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8390 | | }
8391 | | m0 := mload(0x00)
8392 | | m1 := mload(0x20)
8393 | | m2 := mload(0x40)
8394 | | m3 := mload(0x60)
8395 | | m4 := mload(0x80)
8396 | | m5 := mload(0xa0)
8397 | | m6 := mload(0xc0)
8398 | | // Selector of `log(uint256,address,bool,string)`.
8399 | | mstore(0x00, 0x90fb06aa)
8400 | | mstore(0x20, p0)
8401 | | mstore(0x40, p1)
8402 | | mstore(0x60, p2)
8403 | | mstore(0x80, 0x80)
8404 | | writeString(0xa0, p3)
8405 | | }
8406 | | _sendLogPayload(0x1c, 0xc4);
8407 | | /// @solidity memory-safe-assembly
8408 | | assembly {
8409 | | mstore(0x00, m0)
8410 | | mstore(0x20, m1)
8411 | | mstore(0x40, m2)
8412 | | mstore(0x60, m3)
8413 | | mstore(0x80, m4)
8414 | | mstore(0xa0, m5)
8415 | | mstore(0xc0, m6)
8416 | | }
8417 | | }
8418 | |
8419 | | function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
8420 | | bytes32 m0;
8421 | | bytes32 m1;
8422 | | bytes32 m2;
8423 | | bytes32 m3;
8424 | | bytes32 m4;
8425 | | /// @solidity memory-safe-assembly
8426 | | assembly {
8427 | | m0 := mload(0x00)
8428 | | m1 := mload(0x20)
8429 | | m2 := mload(0x40)
8430 | | m3 := mload(0x60)
8431 | | m4 := mload(0x80)
8432 | | // Selector of `log(uint256,address,uint256,address)`.
8433 | | mstore(0x00, 0x15c127b5)
8434 | | mstore(0x20, p0)
8435 | | mstore(0x40, p1)
8436 | | mstore(0x60, p2)
8437 | | mstore(0x80, p3)
8438 | | }
8439 | | _sendLogPayload(0x1c, 0x84);
8440 | | /// @solidity memory-safe-assembly
8441 | | assembly {
8442 | | mstore(0x00, m0)
8443 | | mstore(0x20, m1)
8444 | | mstore(0x40, m2)
8445 | | mstore(0x60, m3)
8446 | | mstore(0x80, m4)
8447 | | }
8448 | | }
8449 | |
8450 | | function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
8451 | | bytes32 m0;
8452 | | bytes32 m1;
8453 | | bytes32 m2;
8454 | | bytes32 m3;
8455 | | bytes32 m4;
8456 | | /// @solidity memory-safe-assembly
8457 | | assembly {
8458 | | m0 := mload(0x00)
8459 | | m1 := mload(0x20)
8460 | | m2 := mload(0x40)
8461 | | m3 := mload(0x60)
8462 | | m4 := mload(0x80)
8463 | | // Selector of `log(uint256,address,uint256,bool)`.
8464 | | mstore(0x00, 0x5f743a7c)
8465 | | mstore(0x20, p0)
8466 | | mstore(0x40, p1)
8467 | | mstore(0x60, p2)
8468 | | mstore(0x80, p3)
8469 | | }
8470 | | _sendLogPayload(0x1c, 0x84);
8471 | | /// @solidity memory-safe-assembly
8472 | | assembly {
8473 | | mstore(0x00, m0)
8474 | | mstore(0x20, m1)
8475 | | mstore(0x40, m2)
8476 | | mstore(0x60, m3)
8477 | | mstore(0x80, m4)
8478 | | }
8479 | | }
8480 | |
8481 | | function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
8482 | | bytes32 m0;
8483 | | bytes32 m1;
8484 | | bytes32 m2;
8485 | | bytes32 m3;
8486 | | bytes32 m4;
8487 | | /// @solidity memory-safe-assembly
8488 | | assembly {
8489 | | m0 := mload(0x00)
8490 | | m1 := mload(0x20)
8491 | | m2 := mload(0x40)
8492 | | m3 := mload(0x60)
8493 | | m4 := mload(0x80)
8494 | | // Selector of `log(uint256,address,uint256,uint256)`.
8495 | | mstore(0x00, 0x0c9cd9c1)
8496 | | mstore(0x20, p0)
8497 | | mstore(0x40, p1)
8498 | | mstore(0x60, p2)
8499 | | mstore(0x80, p3)
8500 | | }
8501 | | _sendLogPayload(0x1c, 0x84);
8502 | | /// @solidity memory-safe-assembly
8503 | | assembly {
8504 | | mstore(0x00, m0)
8505 | | mstore(0x20, m1)
8506 | | mstore(0x40, m2)
8507 | | mstore(0x60, m3)
8508 | | mstore(0x80, m4)
8509 | | }
8510 | | }
8511 | |
8512 | | function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure {
8513 | | bytes32 m0;
8514 | | bytes32 m1;
8515 | | bytes32 m2;
8516 | | bytes32 m3;
8517 | | bytes32 m4;
8518 | | bytes32 m5;
8519 | | bytes32 m6;
8520 | | /// @solidity memory-safe-assembly
8521 | | assembly {
8522 | | function writeString(pos, w) {
8523 | | let length := 0
8524 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8525 | | mstore(pos, length)
8526 | | let shift := sub(256, shl(3, length))
8527 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8528 | | }
8529 | | m0 := mload(0x00)
8530 | | m1 := mload(0x20)
8531 | | m2 := mload(0x40)
8532 | | m3 := mload(0x60)
8533 | | m4 := mload(0x80)
8534 | | m5 := mload(0xa0)
8535 | | m6 := mload(0xc0)
8536 | | // Selector of `log(uint256,address,uint256,string)`.
8537 | | mstore(0x00, 0xddb06521)
8538 | | mstore(0x20, p0)
8539 | | mstore(0x40, p1)
8540 | | mstore(0x60, p2)
8541 | | mstore(0x80, 0x80)
8542 | | writeString(0xa0, p3)
8543 | | }
8544 | | _sendLogPayload(0x1c, 0xc4);
8545 | | /// @solidity memory-safe-assembly
8546 | | assembly {
8547 | | mstore(0x00, m0)
8548 | | mstore(0x20, m1)
8549 | | mstore(0x40, m2)
8550 | | mstore(0x60, m3)
8551 | | mstore(0x80, m4)
8552 | | mstore(0xa0, m5)
8553 | | mstore(0xc0, m6)
8554 | | }
8555 | | }
8556 | |
8557 | | function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure {
8558 | | bytes32 m0;
8559 | | bytes32 m1;
8560 | | bytes32 m2;
8561 | | bytes32 m3;
8562 | | bytes32 m4;
8563 | | bytes32 m5;
8564 | | bytes32 m6;
8565 | | /// @solidity memory-safe-assembly
8566 | | assembly {
8567 | | function writeString(pos, w) {
8568 | | let length := 0
8569 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8570 | | mstore(pos, length)
8571 | | let shift := sub(256, shl(3, length))
8572 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8573 | | }
8574 | | m0 := mload(0x00)
8575 | | m1 := mload(0x20)
8576 | | m2 := mload(0x40)
8577 | | m3 := mload(0x60)
8578 | | m4 := mload(0x80)
8579 | | m5 := mload(0xa0)
8580 | | m6 := mload(0xc0)
8581 | | // Selector of `log(uint256,address,string,address)`.
8582 | | mstore(0x00, 0x9cba8fff)
8583 | | mstore(0x20, p0)
8584 | | mstore(0x40, p1)
8585 | | mstore(0x60, 0x80)
8586 | | mstore(0x80, p3)
8587 | | writeString(0xa0, p2)
8588 | | }
8589 | | _sendLogPayload(0x1c, 0xc4);
8590 | | /// @solidity memory-safe-assembly
8591 | | assembly {
8592 | | mstore(0x00, m0)
8593 | | mstore(0x20, m1)
8594 | | mstore(0x40, m2)
8595 | | mstore(0x60, m3)
8596 | | mstore(0x80, m4)
8597 | | mstore(0xa0, m5)
8598 | | mstore(0xc0, m6)
8599 | | }
8600 | | }
8601 | |
8602 | | function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure {
8603 | | bytes32 m0;
8604 | | bytes32 m1;
8605 | | bytes32 m2;
8606 | | bytes32 m3;
8607 | | bytes32 m4;
8608 | | bytes32 m5;
8609 | | bytes32 m6;
8610 | | /// @solidity memory-safe-assembly
8611 | | assembly {
8612 | | function writeString(pos, w) {
8613 | | let length := 0
8614 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8615 | | mstore(pos, length)
8616 | | let shift := sub(256, shl(3, length))
8617 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8618 | | }
8619 | | m0 := mload(0x00)
8620 | | m1 := mload(0x20)
8621 | | m2 := mload(0x40)
8622 | | m3 := mload(0x60)
8623 | | m4 := mload(0x80)
8624 | | m5 := mload(0xa0)
8625 | | m6 := mload(0xc0)
8626 | | // Selector of `log(uint256,address,string,bool)`.
8627 | | mstore(0x00, 0xcc32ab07)
8628 | | mstore(0x20, p0)
8629 | | mstore(0x40, p1)
8630 | | mstore(0x60, 0x80)
8631 | | mstore(0x80, p3)
8632 | | writeString(0xa0, p2)
8633 | | }
8634 | | _sendLogPayload(0x1c, 0xc4);
8635 | | /// @solidity memory-safe-assembly
8636 | | assembly {
8637 | | mstore(0x00, m0)
8638 | | mstore(0x20, m1)
8639 | | mstore(0x40, m2)
8640 | | mstore(0x60, m3)
8641 | | mstore(0x80, m4)
8642 | | mstore(0xa0, m5)
8643 | | mstore(0xc0, m6)
8644 | | }
8645 | | }
8646 | |
8647 | | function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure {
8648 | | bytes32 m0;
8649 | | bytes32 m1;
8650 | | bytes32 m2;
8651 | | bytes32 m3;
8652 | | bytes32 m4;
8653 | | bytes32 m5;
8654 | | bytes32 m6;
8655 | | /// @solidity memory-safe-assembly
8656 | | assembly {
8657 | | function writeString(pos, w) {
8658 | | let length := 0
8659 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8660 | | mstore(pos, length)
8661 | | let shift := sub(256, shl(3, length))
8662 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8663 | | }
8664 | | m0 := mload(0x00)
8665 | | m1 := mload(0x20)
8666 | | m2 := mload(0x40)
8667 | | m3 := mload(0x60)
8668 | | m4 := mload(0x80)
8669 | | m5 := mload(0xa0)
8670 | | m6 := mload(0xc0)
8671 | | // Selector of `log(uint256,address,string,uint256)`.
8672 | | mstore(0x00, 0x46826b5d)
8673 | | mstore(0x20, p0)
8674 | | mstore(0x40, p1)
8675 | | mstore(0x60, 0x80)
8676 | | mstore(0x80, p3)
8677 | | writeString(0xa0, p2)
8678 | | }
8679 | | _sendLogPayload(0x1c, 0xc4);
8680 | | /// @solidity memory-safe-assembly
8681 | | assembly {
8682 | | mstore(0x00, m0)
8683 | | mstore(0x20, m1)
8684 | | mstore(0x40, m2)
8685 | | mstore(0x60, m3)
8686 | | mstore(0x80, m4)
8687 | | mstore(0xa0, m5)
8688 | | mstore(0xc0, m6)
8689 | | }
8690 | | }
8691 | |
8692 | | function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
8693 | | bytes32 m0;
8694 | | bytes32 m1;
8695 | | bytes32 m2;
8696 | | bytes32 m3;
8697 | | bytes32 m4;
8698 | | bytes32 m5;
8699 | | bytes32 m6;
8700 | | bytes32 m7;
8701 | | bytes32 m8;
8702 | | /// @solidity memory-safe-assembly
8703 | | assembly {
8704 | | function writeString(pos, w) {
8705 | | let length := 0
8706 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8707 | | mstore(pos, length)
8708 | | let shift := sub(256, shl(3, length))
8709 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8710 | | }
8711 | | m0 := mload(0x00)
8712 | | m1 := mload(0x20)
8713 | | m2 := mload(0x40)
8714 | | m3 := mload(0x60)
8715 | | m4 := mload(0x80)
8716 | | m5 := mload(0xa0)
8717 | | m6 := mload(0xc0)
8718 | | m7 := mload(0xe0)
8719 | | m8 := mload(0x100)
8720 | | // Selector of `log(uint256,address,string,string)`.
8721 | | mstore(0x00, 0x3e128ca3)
8722 | | mstore(0x20, p0)
8723 | | mstore(0x40, p1)
8724 | | mstore(0x60, 0x80)
8725 | | mstore(0x80, 0xc0)
8726 | | writeString(0xa0, p2)
8727 | | writeString(0xe0, p3)
8728 | | }
8729 | | _sendLogPayload(0x1c, 0x104);
8730 | | /// @solidity memory-safe-assembly
8731 | | assembly {
8732 | | mstore(0x00, m0)
8733 | | mstore(0x20, m1)
8734 | | mstore(0x40, m2)
8735 | | mstore(0x60, m3)
8736 | | mstore(0x80, m4)
8737 | | mstore(0xa0, m5)
8738 | | mstore(0xc0, m6)
8739 | | mstore(0xe0, m7)
8740 | | mstore(0x100, m8)
8741 | | }
8742 | | }
8743 | |
8744 | | function log(uint256 p0, bool p1, address p2, address p3) internal pure {
8745 | | bytes32 m0;
8746 | | bytes32 m1;
8747 | | bytes32 m2;
8748 | | bytes32 m3;
8749 | | bytes32 m4;
8750 | | /// @solidity memory-safe-assembly
8751 | | assembly {
8752 | | m0 := mload(0x00)
8753 | | m1 := mload(0x20)
8754 | | m2 := mload(0x40)
8755 | | m3 := mload(0x60)
8756 | | m4 := mload(0x80)
8757 | | // Selector of `log(uint256,bool,address,address)`.
8758 | | mstore(0x00, 0xa1ef4cbb)
8759 | | mstore(0x20, p0)
8760 | | mstore(0x40, p1)
8761 | | mstore(0x60, p2)
8762 | | mstore(0x80, p3)
8763 | | }
8764 | | _sendLogPayload(0x1c, 0x84);
8765 | | /// @solidity memory-safe-assembly
8766 | | assembly {
8767 | | mstore(0x00, m0)
8768 | | mstore(0x20, m1)
8769 | | mstore(0x40, m2)
8770 | | mstore(0x60, m3)
8771 | | mstore(0x80, m4)
8772 | | }
8773 | | }
8774 | |
8775 | | function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
8776 | | bytes32 m0;
8777 | | bytes32 m1;
8778 | | bytes32 m2;
8779 | | bytes32 m3;
8780 | | bytes32 m4;
8781 | | /// @solidity memory-safe-assembly
8782 | | assembly {
8783 | | m0 := mload(0x00)
8784 | | m1 := mload(0x20)
8785 | | m2 := mload(0x40)
8786 | | m3 := mload(0x60)
8787 | | m4 := mload(0x80)
8788 | | // Selector of `log(uint256,bool,address,bool)`.
8789 | | mstore(0x00, 0x454d54a5)
8790 | | mstore(0x20, p0)
8791 | | mstore(0x40, p1)
8792 | | mstore(0x60, p2)
8793 | | mstore(0x80, p3)
8794 | | }
8795 | | _sendLogPayload(0x1c, 0x84);
8796 | | /// @solidity memory-safe-assembly
8797 | | assembly {
8798 | | mstore(0x00, m0)
8799 | | mstore(0x20, m1)
8800 | | mstore(0x40, m2)
8801 | | mstore(0x60, m3)
8802 | | mstore(0x80, m4)
8803 | | }
8804 | | }
8805 | |
8806 | | function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
8807 | | bytes32 m0;
8808 | | bytes32 m1;
8809 | | bytes32 m2;
8810 | | bytes32 m3;
8811 | | bytes32 m4;
8812 | | /// @solidity memory-safe-assembly
8813 | | assembly {
8814 | | m0 := mload(0x00)
8815 | | m1 := mload(0x20)
8816 | | m2 := mload(0x40)
8817 | | m3 := mload(0x60)
8818 | | m4 := mload(0x80)
8819 | | // Selector of `log(uint256,bool,address,uint256)`.
8820 | | mstore(0x00, 0x078287f5)
8821 | | mstore(0x20, p0)
8822 | | mstore(0x40, p1)
8823 | | mstore(0x60, p2)
8824 | | mstore(0x80, p3)
8825 | | }
8826 | | _sendLogPayload(0x1c, 0x84);
8827 | | /// @solidity memory-safe-assembly
8828 | | assembly {
8829 | | mstore(0x00, m0)
8830 | | mstore(0x20, m1)
8831 | | mstore(0x40, m2)
8832 | | mstore(0x60, m3)
8833 | | mstore(0x80, m4)
8834 | | }
8835 | | }
8836 | |
8837 | | function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure {
8838 | | bytes32 m0;
8839 | | bytes32 m1;
8840 | | bytes32 m2;
8841 | | bytes32 m3;
8842 | | bytes32 m4;
8843 | | bytes32 m5;
8844 | | bytes32 m6;
8845 | | /// @solidity memory-safe-assembly
8846 | | assembly {
8847 | | function writeString(pos, w) {
8848 | | let length := 0
8849 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8850 | | mstore(pos, length)
8851 | | let shift := sub(256, shl(3, length))
8852 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8853 | | }
8854 | | m0 := mload(0x00)
8855 | | m1 := mload(0x20)
8856 | | m2 := mload(0x40)
8857 | | m3 := mload(0x60)
8858 | | m4 := mload(0x80)
8859 | | m5 := mload(0xa0)
8860 | | m6 := mload(0xc0)
8861 | | // Selector of `log(uint256,bool,address,string)`.
8862 | | mstore(0x00, 0xade052c7)
8863 | | mstore(0x20, p0)
8864 | | mstore(0x40, p1)
8865 | | mstore(0x60, p2)
8866 | | mstore(0x80, 0x80)
8867 | | writeString(0xa0, p3)
8868 | | }
8869 | | _sendLogPayload(0x1c, 0xc4);
8870 | | /// @solidity memory-safe-assembly
8871 | | assembly {
8872 | | mstore(0x00, m0)
8873 | | mstore(0x20, m1)
8874 | | mstore(0x40, m2)
8875 | | mstore(0x60, m3)
8876 | | mstore(0x80, m4)
8877 | | mstore(0xa0, m5)
8878 | | mstore(0xc0, m6)
8879 | | }
8880 | | }
8881 | |
8882 | | function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
8883 | | bytes32 m0;
8884 | | bytes32 m1;
8885 | | bytes32 m2;
8886 | | bytes32 m3;
8887 | | bytes32 m4;
8888 | | /// @solidity memory-safe-assembly
8889 | | assembly {
8890 | | m0 := mload(0x00)
8891 | | m1 := mload(0x20)
8892 | | m2 := mload(0x40)
8893 | | m3 := mload(0x60)
8894 | | m4 := mload(0x80)
8895 | | // Selector of `log(uint256,bool,bool,address)`.
8896 | | mstore(0x00, 0x69640b59)
8897 | | mstore(0x20, p0)
8898 | | mstore(0x40, p1)
8899 | | mstore(0x60, p2)
8900 | | mstore(0x80, p3)
8901 | | }
8902 | | _sendLogPayload(0x1c, 0x84);
8903 | | /// @solidity memory-safe-assembly
8904 | | assembly {
8905 | | mstore(0x00, m0)
8906 | | mstore(0x20, m1)
8907 | | mstore(0x40, m2)
8908 | | mstore(0x60, m3)
8909 | | mstore(0x80, m4)
8910 | | }
8911 | | }
8912 | |
8913 | | function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
8914 | | bytes32 m0;
8915 | | bytes32 m1;
8916 | | bytes32 m2;
8917 | | bytes32 m3;
8918 | | bytes32 m4;
8919 | | /// @solidity memory-safe-assembly
8920 | | assembly {
8921 | | m0 := mload(0x00)
8922 | | m1 := mload(0x20)
8923 | | m2 := mload(0x40)
8924 | | m3 := mload(0x60)
8925 | | m4 := mload(0x80)
8926 | | // Selector of `log(uint256,bool,bool,bool)`.
8927 | | mstore(0x00, 0xb6f577a1)
8928 | | mstore(0x20, p0)
8929 | | mstore(0x40, p1)
8930 | | mstore(0x60, p2)
8931 | | mstore(0x80, p3)
8932 | | }
8933 | | _sendLogPayload(0x1c, 0x84);
8934 | | /// @solidity memory-safe-assembly
8935 | | assembly {
8936 | | mstore(0x00, m0)
8937 | | mstore(0x20, m1)
8938 | | mstore(0x40, m2)
8939 | | mstore(0x60, m3)
8940 | | mstore(0x80, m4)
8941 | | }
8942 | | }
8943 | |
8944 | | function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
8945 | | bytes32 m0;
8946 | | bytes32 m1;
8947 | | bytes32 m2;
8948 | | bytes32 m3;
8949 | | bytes32 m4;
8950 | | /// @solidity memory-safe-assembly
8951 | | assembly {
8952 | | m0 := mload(0x00)
8953 | | m1 := mload(0x20)
8954 | | m2 := mload(0x40)
8955 | | m3 := mload(0x60)
8956 | | m4 := mload(0x80)
8957 | | // Selector of `log(uint256,bool,bool,uint256)`.
8958 | | mstore(0x00, 0x7464ce23)
8959 | | mstore(0x20, p0)
8960 | | mstore(0x40, p1)
8961 | | mstore(0x60, p2)
8962 | | mstore(0x80, p3)
8963 | | }
8964 | | _sendLogPayload(0x1c, 0x84);
8965 | | /// @solidity memory-safe-assembly
8966 | | assembly {
8967 | | mstore(0x00, m0)
8968 | | mstore(0x20, m1)
8969 | | mstore(0x40, m2)
8970 | | mstore(0x60, m3)
8971 | | mstore(0x80, m4)
8972 | | }
8973 | | }
8974 | |
8975 | | function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure {
8976 | | bytes32 m0;
8977 | | bytes32 m1;
8978 | | bytes32 m2;
8979 | | bytes32 m3;
8980 | | bytes32 m4;
8981 | | bytes32 m5;
8982 | | bytes32 m6;
8983 | | /// @solidity memory-safe-assembly
8984 | | assembly {
8985 | | function writeString(pos, w) {
8986 | | let length := 0
8987 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8988 | | mstore(pos, length)
8989 | | let shift := sub(256, shl(3, length))
8990 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8991 | | }
8992 | | m0 := mload(0x00)
8993 | | m1 := mload(0x20)
8994 | | m2 := mload(0x40)
8995 | | m3 := mload(0x60)
8996 | | m4 := mload(0x80)
8997 | | m5 := mload(0xa0)
8998 | | m6 := mload(0xc0)
8999 | | // Selector of `log(uint256,bool,bool,string)`.
9000 | | mstore(0x00, 0xdddb9561)
9001 | | mstore(0x20, p0)
9002 | | mstore(0x40, p1)
9003 | | mstore(0x60, p2)
9004 | | mstore(0x80, 0x80)
9005 | | writeString(0xa0, p3)
9006 | | }
9007 | | _sendLogPayload(0x1c, 0xc4);
9008 | | /// @solidity memory-safe-assembly
9009 | | assembly {
9010 | | mstore(0x00, m0)
9011 | | mstore(0x20, m1)
9012 | | mstore(0x40, m2)
9013 | | mstore(0x60, m3)
9014 | | mstore(0x80, m4)
9015 | | mstore(0xa0, m5)
9016 | | mstore(0xc0, m6)
9017 | | }
9018 | | }
9019 | |
9020 | | function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
9021 | | bytes32 m0;
9022 | | bytes32 m1;
9023 | | bytes32 m2;
9024 | | bytes32 m3;
9025 | | bytes32 m4;
9026 | | /// @solidity memory-safe-assembly
9027 | | assembly {
9028 | | m0 := mload(0x00)
9029 | | m1 := mload(0x20)
9030 | | m2 := mload(0x40)
9031 | | m3 := mload(0x60)
9032 | | m4 := mload(0x80)
9033 | | // Selector of `log(uint256,bool,uint256,address)`.
9034 | | mstore(0x00, 0x88cb6041)
9035 | | mstore(0x20, p0)
9036 | | mstore(0x40, p1)
9037 | | mstore(0x60, p2)
9038 | | mstore(0x80, p3)
9039 | | }
9040 | | _sendLogPayload(0x1c, 0x84);
9041 | | /// @solidity memory-safe-assembly
9042 | | assembly {
9043 | | mstore(0x00, m0)
9044 | | mstore(0x20, m1)
9045 | | mstore(0x40, m2)
9046 | | mstore(0x60, m3)
9047 | | mstore(0x80, m4)
9048 | | }
9049 | | }
9050 | |
9051 | | function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
9052 | | bytes32 m0;
9053 | | bytes32 m1;
9054 | | bytes32 m2;
9055 | | bytes32 m3;
9056 | | bytes32 m4;
9057 | | /// @solidity memory-safe-assembly
9058 | | assembly {
9059 | | m0 := mload(0x00)
9060 | | m1 := mload(0x20)
9061 | | m2 := mload(0x40)
9062 | | m3 := mload(0x60)
9063 | | m4 := mload(0x80)
9064 | | // Selector of `log(uint256,bool,uint256,bool)`.
9065 | | mstore(0x00, 0x91a02e2a)
9066 | | mstore(0x20, p0)
9067 | | mstore(0x40, p1)
9068 | | mstore(0x60, p2)
9069 | | mstore(0x80, p3)
9070 | | }
9071 | | _sendLogPayload(0x1c, 0x84);
9072 | | /// @solidity memory-safe-assembly
9073 | | assembly {
9074 | | mstore(0x00, m0)
9075 | | mstore(0x20, m1)
9076 | | mstore(0x40, m2)
9077 | | mstore(0x60, m3)
9078 | | mstore(0x80, m4)
9079 | | }
9080 | | }
9081 | |
9082 | | function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
9083 | | bytes32 m0;
9084 | | bytes32 m1;
9085 | | bytes32 m2;
9086 | | bytes32 m3;
9087 | | bytes32 m4;
9088 | | /// @solidity memory-safe-assembly
9089 | | assembly {
9090 | | m0 := mload(0x00)
9091 | | m1 := mload(0x20)
9092 | | m2 := mload(0x40)
9093 | | m3 := mload(0x60)
9094 | | m4 := mload(0x80)
9095 | | // Selector of `log(uint256,bool,uint256,uint256)`.
9096 | | mstore(0x00, 0xc6acc7a8)
9097 | | mstore(0x20, p0)
9098 | | mstore(0x40, p1)
9099 | | mstore(0x60, p2)
9100 | | mstore(0x80, p3)
9101 | | }
9102 | | _sendLogPayload(0x1c, 0x84);
9103 | | /// @solidity memory-safe-assembly
9104 | | assembly {
9105 | | mstore(0x00, m0)
9106 | | mstore(0x20, m1)
9107 | | mstore(0x40, m2)
9108 | | mstore(0x60, m3)
9109 | | mstore(0x80, m4)
9110 | | }
9111 | | }
9112 | |
9113 | | function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
9114 | | bytes32 m0;
9115 | | bytes32 m1;
9116 | | bytes32 m2;
9117 | | bytes32 m3;
9118 | | bytes32 m4;
9119 | | bytes32 m5;
9120 | | bytes32 m6;
9121 | | /// @solidity memory-safe-assembly
9122 | | assembly {
9123 | | function writeString(pos, w) {
9124 | | let length := 0
9125 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9126 | | mstore(pos, length)
9127 | | let shift := sub(256, shl(3, length))
9128 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9129 | | }
9130 | | m0 := mload(0x00)
9131 | | m1 := mload(0x20)
9132 | | m2 := mload(0x40)
9133 | | m3 := mload(0x60)
9134 | | m4 := mload(0x80)
9135 | | m5 := mload(0xa0)
9136 | | m6 := mload(0xc0)
9137 | | // Selector of `log(uint256,bool,uint256,string)`.
9138 | | mstore(0x00, 0xde03e774)
9139 | | mstore(0x20, p0)
9140 | | mstore(0x40, p1)
9141 | | mstore(0x60, p2)
9142 | | mstore(0x80, 0x80)
9143 | | writeString(0xa0, p3)
9144 | | }
9145 | | _sendLogPayload(0x1c, 0xc4);
9146 | | /// @solidity memory-safe-assembly
9147 | | assembly {
9148 | | mstore(0x00, m0)
9149 | | mstore(0x20, m1)
9150 | | mstore(0x40, m2)
9151 | | mstore(0x60, m3)
9152 | | mstore(0x80, m4)
9153 | | mstore(0xa0, m5)
9154 | | mstore(0xc0, m6)
9155 | | }
9156 | | }
9157 | |
9158 | | function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure {
9159 | | bytes32 m0;
9160 | | bytes32 m1;
9161 | | bytes32 m2;
9162 | | bytes32 m3;
9163 | | bytes32 m4;
9164 | | bytes32 m5;
9165 | | bytes32 m6;
9166 | | /// @solidity memory-safe-assembly
9167 | | assembly {
9168 | | function writeString(pos, w) {
9169 | | let length := 0
9170 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9171 | | mstore(pos, length)
9172 | | let shift := sub(256, shl(3, length))
9173 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9174 | | }
9175 | | m0 := mload(0x00)
9176 | | m1 := mload(0x20)
9177 | | m2 := mload(0x40)
9178 | | m3 := mload(0x60)
9179 | | m4 := mload(0x80)
9180 | | m5 := mload(0xa0)
9181 | | m6 := mload(0xc0)
9182 | | // Selector of `log(uint256,bool,string,address)`.
9183 | | mstore(0x00, 0xef529018)
9184 | | mstore(0x20, p0)
9185 | | mstore(0x40, p1)
9186 | | mstore(0x60, 0x80)
9187 | | mstore(0x80, p3)
9188 | | writeString(0xa0, p2)
9189 | | }
9190 | | _sendLogPayload(0x1c, 0xc4);
9191 | | /// @solidity memory-safe-assembly
9192 | | assembly {
9193 | | mstore(0x00, m0)
9194 | | mstore(0x20, m1)
9195 | | mstore(0x40, m2)
9196 | | mstore(0x60, m3)
9197 | | mstore(0x80, m4)
9198 | | mstore(0xa0, m5)
9199 | | mstore(0xc0, m6)
9200 | | }
9201 | | }
9202 | |
9203 | | function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure {
9204 | | bytes32 m0;
9205 | | bytes32 m1;
9206 | | bytes32 m2;
9207 | | bytes32 m3;
9208 | | bytes32 m4;
9209 | | bytes32 m5;
9210 | | bytes32 m6;
9211 | | /// @solidity memory-safe-assembly
9212 | | assembly {
9213 | | function writeString(pos, w) {
9214 | | let length := 0
9215 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9216 | | mstore(pos, length)
9217 | | let shift := sub(256, shl(3, length))
9218 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9219 | | }
9220 | | m0 := mload(0x00)
9221 | | m1 := mload(0x20)
9222 | | m2 := mload(0x40)
9223 | | m3 := mload(0x60)
9224 | | m4 := mload(0x80)
9225 | | m5 := mload(0xa0)
9226 | | m6 := mload(0xc0)
9227 | | // Selector of `log(uint256,bool,string,bool)`.
9228 | | mstore(0x00, 0xeb928d7f)
9229 | | mstore(0x20, p0)
9230 | | mstore(0x40, p1)
9231 | | mstore(0x60, 0x80)
9232 | | mstore(0x80, p3)
9233 | | writeString(0xa0, p2)
9234 | | }
9235 | | _sendLogPayload(0x1c, 0xc4);
9236 | | /// @solidity memory-safe-assembly
9237 | | assembly {
9238 | | mstore(0x00, m0)
9239 | | mstore(0x20, m1)
9240 | | mstore(0x40, m2)
9241 | | mstore(0x60, m3)
9242 | | mstore(0x80, m4)
9243 | | mstore(0xa0, m5)
9244 | | mstore(0xc0, m6)
9245 | | }
9246 | | }
9247 | |
9248 | | function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
9249 | | bytes32 m0;
9250 | | bytes32 m1;
9251 | | bytes32 m2;
9252 | | bytes32 m3;
9253 | | bytes32 m4;
9254 | | bytes32 m5;
9255 | | bytes32 m6;
9256 | | /// @solidity memory-safe-assembly
9257 | | assembly {
9258 | | function writeString(pos, w) {
9259 | | let length := 0
9260 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9261 | | mstore(pos, length)
9262 | | let shift := sub(256, shl(3, length))
9263 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9264 | | }
9265 | | m0 := mload(0x00)
9266 | | m1 := mload(0x20)
9267 | | m2 := mload(0x40)
9268 | | m3 := mload(0x60)
9269 | | m4 := mload(0x80)
9270 | | m5 := mload(0xa0)
9271 | | m6 := mload(0xc0)
9272 | | // Selector of `log(uint256,bool,string,uint256)`.
9273 | | mstore(0x00, 0x2c1d0746)
9274 | | mstore(0x20, p0)
9275 | | mstore(0x40, p1)
9276 | | mstore(0x60, 0x80)
9277 | | mstore(0x80, p3)
9278 | | writeString(0xa0, p2)
9279 | | }
9280 | | _sendLogPayload(0x1c, 0xc4);
9281 | | /// @solidity memory-safe-assembly
9282 | | assembly {
9283 | | mstore(0x00, m0)
9284 | | mstore(0x20, m1)
9285 | | mstore(0x40, m2)
9286 | | mstore(0x60, m3)
9287 | | mstore(0x80, m4)
9288 | | mstore(0xa0, m5)
9289 | | mstore(0xc0, m6)
9290 | | }
9291 | | }
9292 | |
9293 | | function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
9294 | | bytes32 m0;
9295 | | bytes32 m1;
9296 | | bytes32 m2;
9297 | | bytes32 m3;
9298 | | bytes32 m4;
9299 | | bytes32 m5;
9300 | | bytes32 m6;
9301 | | bytes32 m7;
9302 | | bytes32 m8;
9303 | | /// @solidity memory-safe-assembly
9304 | | assembly {
9305 | | function writeString(pos, w) {
9306 | | let length := 0
9307 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9308 | | mstore(pos, length)
9309 | | let shift := sub(256, shl(3, length))
9310 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9311 | | }
9312 | | m0 := mload(0x00)
9313 | | m1 := mload(0x20)
9314 | | m2 := mload(0x40)
9315 | | m3 := mload(0x60)
9316 | | m4 := mload(0x80)
9317 | | m5 := mload(0xa0)
9318 | | m6 := mload(0xc0)
9319 | | m7 := mload(0xe0)
9320 | | m8 := mload(0x100)
9321 | | // Selector of `log(uint256,bool,string,string)`.
9322 | | mstore(0x00, 0x68c8b8bd)
9323 | | mstore(0x20, p0)
9324 | | mstore(0x40, p1)
9325 | | mstore(0x60, 0x80)
9326 | | mstore(0x80, 0xc0)
9327 | | writeString(0xa0, p2)
9328 | | writeString(0xe0, p3)
9329 | | }
9330 | | _sendLogPayload(0x1c, 0x104);
9331 | | /// @solidity memory-safe-assembly
9332 | | assembly {
9333 | | mstore(0x00, m0)
9334 | | mstore(0x20, m1)
9335 | | mstore(0x40, m2)
9336 | | mstore(0x60, m3)
9337 | | mstore(0x80, m4)
9338 | | mstore(0xa0, m5)
9339 | | mstore(0xc0, m6)
9340 | | mstore(0xe0, m7)
9341 | | mstore(0x100, m8)
9342 | | }
9343 | | }
9344 | |
9345 | | function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
9346 | | bytes32 m0;
9347 | | bytes32 m1;
9348 | | bytes32 m2;
9349 | | bytes32 m3;
9350 | | bytes32 m4;
9351 | | /// @solidity memory-safe-assembly
9352 | | assembly {
9353 | | m0 := mload(0x00)
9354 | | m1 := mload(0x20)
9355 | | m2 := mload(0x40)
9356 | | m3 := mload(0x60)
9357 | | m4 := mload(0x80)
9358 | | // Selector of `log(uint256,uint256,address,address)`.
9359 | | mstore(0x00, 0x56a5d1b1)
9360 | | mstore(0x20, p0)
9361 | | mstore(0x40, p1)
9362 | | mstore(0x60, p2)
9363 | | mstore(0x80, p3)
9364 | | }
9365 | | _sendLogPayload(0x1c, 0x84);
9366 | | /// @solidity memory-safe-assembly
9367 | | assembly {
9368 | | mstore(0x00, m0)
9369 | | mstore(0x20, m1)
9370 | | mstore(0x40, m2)
9371 | | mstore(0x60, m3)
9372 | | mstore(0x80, m4)
9373 | | }
9374 | | }
9375 | |
9376 | | function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
9377 | | bytes32 m0;
9378 | | bytes32 m1;
9379 | | bytes32 m2;
9380 | | bytes32 m3;
9381 | | bytes32 m4;
9382 | | /// @solidity memory-safe-assembly
9383 | | assembly {
9384 | | m0 := mload(0x00)
9385 | | m1 := mload(0x20)
9386 | | m2 := mload(0x40)
9387 | | m3 := mload(0x60)
9388 | | m4 := mload(0x80)
9389 | | // Selector of `log(uint256,uint256,address,bool)`.
9390 | | mstore(0x00, 0x15cac476)
9391 | | mstore(0x20, p0)
9392 | | mstore(0x40, p1)
9393 | | mstore(0x60, p2)
9394 | | mstore(0x80, p3)
9395 | | }
9396 | | _sendLogPayload(0x1c, 0x84);
9397 | | /// @solidity memory-safe-assembly
9398 | | assembly {
9399 | | mstore(0x00, m0)
9400 | | mstore(0x20, m1)
9401 | | mstore(0x40, m2)
9402 | | mstore(0x60, m3)
9403 | | mstore(0x80, m4)
9404 | | }
9405 | | }
9406 | |
9407 | | function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
9408 | | bytes32 m0;
9409 | | bytes32 m1;
9410 | | bytes32 m2;
9411 | | bytes32 m3;
9412 | | bytes32 m4;
9413 | | /// @solidity memory-safe-assembly
9414 | | assembly {
9415 | | m0 := mload(0x00)
9416 | | m1 := mload(0x20)
9417 | | m2 := mload(0x40)
9418 | | m3 := mload(0x60)
9419 | | m4 := mload(0x80)
9420 | | // Selector of `log(uint256,uint256,address,uint256)`.
9421 | | mstore(0x00, 0x88f6e4b2)
9422 | | mstore(0x20, p0)
9423 | | mstore(0x40, p1)
9424 | | mstore(0x60, p2)
9425 | | mstore(0x80, p3)
9426 | | }
9427 | | _sendLogPayload(0x1c, 0x84);
9428 | | /// @solidity memory-safe-assembly
9429 | | assembly {
9430 | | mstore(0x00, m0)
9431 | | mstore(0x20, m1)
9432 | | mstore(0x40, m2)
9433 | | mstore(0x60, m3)
9434 | | mstore(0x80, m4)
9435 | | }
9436 | | }
9437 | |
9438 | | function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure {
9439 | | bytes32 m0;
9440 | | bytes32 m1;
9441 | | bytes32 m2;
9442 | | bytes32 m3;
9443 | | bytes32 m4;
9444 | | bytes32 m5;
9445 | | bytes32 m6;
9446 | | /// @solidity memory-safe-assembly
9447 | | assembly {
9448 | | function writeString(pos, w) {
9449 | | let length := 0
9450 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9451 | | mstore(pos, length)
9452 | | let shift := sub(256, shl(3, length))
9453 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9454 | | }
9455 | | m0 := mload(0x00)
9456 | | m1 := mload(0x20)
9457 | | m2 := mload(0x40)
9458 | | m3 := mload(0x60)
9459 | | m4 := mload(0x80)
9460 | | m5 := mload(0xa0)
9461 | | m6 := mload(0xc0)
9462 | | // Selector of `log(uint256,uint256,address,string)`.
9463 | | mstore(0x00, 0x6cde40b8)
9464 | | mstore(0x20, p0)
9465 | | mstore(0x40, p1)
9466 | | mstore(0x60, p2)
9467 | | mstore(0x80, 0x80)
9468 | | writeString(0xa0, p3)
9469 | | }
9470 | | _sendLogPayload(0x1c, 0xc4);
9471 | | /// @solidity memory-safe-assembly
9472 | | assembly {
9473 | | mstore(0x00, m0)
9474 | | mstore(0x20, m1)
9475 | | mstore(0x40, m2)
9476 | | mstore(0x60, m3)
9477 | | mstore(0x80, m4)
9478 | | mstore(0xa0, m5)
9479 | | mstore(0xc0, m6)
9480 | | }
9481 | | }
9482 | |
9483 | | function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
9484 | | bytes32 m0;
9485 | | bytes32 m1;
9486 | | bytes32 m2;
9487 | | bytes32 m3;
9488 | | bytes32 m4;
9489 | | /// @solidity memory-safe-assembly
9490 | | assembly {
9491 | | m0 := mload(0x00)
9492 | | m1 := mload(0x20)
9493 | | m2 := mload(0x40)
9494 | | m3 := mload(0x60)
9495 | | m4 := mload(0x80)
9496 | | // Selector of `log(uint256,uint256,bool,address)`.
9497 | | mstore(0x00, 0x9a816a83)
9498 | | mstore(0x20, p0)
9499 | | mstore(0x40, p1)
9500 | | mstore(0x60, p2)
9501 | | mstore(0x80, p3)
9502 | | }
9503 | | _sendLogPayload(0x1c, 0x84);
9504 | | /// @solidity memory-safe-assembly
9505 | | assembly {
9506 | | mstore(0x00, m0)
9507 | | mstore(0x20, m1)
9508 | | mstore(0x40, m2)
9509 | | mstore(0x60, m3)
9510 | | mstore(0x80, m4)
9511 | | }
9512 | | }
9513 | |
9514 | | function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
9515 | | bytes32 m0;
9516 | | bytes32 m1;
9517 | | bytes32 m2;
9518 | | bytes32 m3;
9519 | | bytes32 m4;
9520 | | /// @solidity memory-safe-assembly
9521 | | assembly {
9522 | | m0 := mload(0x00)
9523 | | m1 := mload(0x20)
9524 | | m2 := mload(0x40)
9525 | | m3 := mload(0x60)
9526 | | m4 := mload(0x80)
9527 | | // Selector of `log(uint256,uint256,bool,bool)`.
9528 | | mstore(0x00, 0xab085ae6)
9529 | | mstore(0x20, p0)
9530 | | mstore(0x40, p1)
9531 | | mstore(0x60, p2)
9532 | | mstore(0x80, p3)
9533 | | }
9534 | | _sendLogPayload(0x1c, 0x84);
9535 | | /// @solidity memory-safe-assembly
9536 | | assembly {
9537 | | mstore(0x00, m0)
9538 | | mstore(0x20, m1)
9539 | | mstore(0x40, m2)
9540 | | mstore(0x60, m3)
9541 | | mstore(0x80, m4)
9542 | | }
9543 | | }
9544 | |
9545 | | function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
9546 | | bytes32 m0;
9547 | | bytes32 m1;
9548 | | bytes32 m2;
9549 | | bytes32 m3;
9550 | | bytes32 m4;
9551 | | /// @solidity memory-safe-assembly
9552 | | assembly {
9553 | | m0 := mload(0x00)
9554 | | m1 := mload(0x20)
9555 | | m2 := mload(0x40)
9556 | | m3 := mload(0x60)
9557 | | m4 := mload(0x80)
9558 | | // Selector of `log(uint256,uint256,bool,uint256)`.
9559 | | mstore(0x00, 0xeb7f6fd2)
9560 | | mstore(0x20, p0)
9561 | | mstore(0x40, p1)
9562 | | mstore(0x60, p2)
9563 | | mstore(0x80, p3)
9564 | | }
9565 | | _sendLogPayload(0x1c, 0x84);
9566 | | /// @solidity memory-safe-assembly
9567 | | assembly {
9568 | | mstore(0x00, m0)
9569 | | mstore(0x20, m1)
9570 | | mstore(0x40, m2)
9571 | | mstore(0x60, m3)
9572 | | mstore(0x80, m4)
9573 | | }
9574 | | }
9575 | |
9576 | | function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
9577 | | bytes32 m0;
9578 | | bytes32 m1;
9579 | | bytes32 m2;
9580 | | bytes32 m3;
9581 | | bytes32 m4;
9582 | | bytes32 m5;
9583 | | bytes32 m6;
9584 | | /// @solidity memory-safe-assembly
9585 | | assembly {
9586 | | function writeString(pos, w) {
9587 | | let length := 0
9588 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9589 | | mstore(pos, length)
9590 | | let shift := sub(256, shl(3, length))
9591 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9592 | | }
9593 | | m0 := mload(0x00)
9594 | | m1 := mload(0x20)
9595 | | m2 := mload(0x40)
9596 | | m3 := mload(0x60)
9597 | | m4 := mload(0x80)
9598 | | m5 := mload(0xa0)
9599 | | m6 := mload(0xc0)
9600 | | // Selector of `log(uint256,uint256,bool,string)`.
9601 | | mstore(0x00, 0xa5b4fc99)
9602 | | mstore(0x20, p0)
9603 | | mstore(0x40, p1)
9604 | | mstore(0x60, p2)
9605 | | mstore(0x80, 0x80)
9606 | | writeString(0xa0, p3)
9607 | | }
9608 | | _sendLogPayload(0x1c, 0xc4);
9609 | | /// @solidity memory-safe-assembly
9610 | | assembly {
9611 | | mstore(0x00, m0)
9612 | | mstore(0x20, m1)
9613 | | mstore(0x40, m2)
9614 | | mstore(0x60, m3)
9615 | | mstore(0x80, m4)
9616 | | mstore(0xa0, m5)
9617 | | mstore(0xc0, m6)
9618 | | }
9619 | | }
9620 | |
9621 | | function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
9622 | | bytes32 m0;
9623 | | bytes32 m1;
9624 | | bytes32 m2;
9625 | | bytes32 m3;
9626 | | bytes32 m4;
9627 | | /// @solidity memory-safe-assembly
9628 | | assembly {
9629 | | m0 := mload(0x00)
9630 | | m1 := mload(0x20)
9631 | | m2 := mload(0x40)
9632 | | m3 := mload(0x60)
9633 | | m4 := mload(0x80)
9634 | | // Selector of `log(uint256,uint256,uint256,address)`.
9635 | | mstore(0x00, 0xfa8185af)
9636 | | mstore(0x20, p0)
9637 | | mstore(0x40, p1)
9638 | | mstore(0x60, p2)
9639 | | mstore(0x80, p3)
9640 | | }
9641 | | _sendLogPayload(0x1c, 0x84);
9642 | | /// @solidity memory-safe-assembly
9643 | | assembly {
9644 | | mstore(0x00, m0)
9645 | | mstore(0x20, m1)
9646 | | mstore(0x40, m2)
9647 | | mstore(0x60, m3)
9648 | | mstore(0x80, m4)
9649 | | }
9650 | | }
9651 | |
9652 | | function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
9653 | | bytes32 m0;
9654 | | bytes32 m1;
9655 | | bytes32 m2;
9656 | | bytes32 m3;
9657 | | bytes32 m4;
9658 | | /// @solidity memory-safe-assembly
9659 | | assembly {
9660 | | m0 := mload(0x00)
9661 | | m1 := mload(0x20)
9662 | | m2 := mload(0x40)
9663 | | m3 := mload(0x60)
9664 | | m4 := mload(0x80)
9665 | | // Selector of `log(uint256,uint256,uint256,bool)`.
9666 | | mstore(0x00, 0xc598d185)
9667 | | mstore(0x20, p0)
9668 | | mstore(0x40, p1)
9669 | | mstore(0x60, p2)
9670 | | mstore(0x80, p3)
9671 | | }
9672 | | _sendLogPayload(0x1c, 0x84);
9673 | | /// @solidity memory-safe-assembly
9674 | | assembly {
9675 | | mstore(0x00, m0)
9676 | | mstore(0x20, m1)
9677 | | mstore(0x40, m2)
9678 | | mstore(0x60, m3)
9679 | | mstore(0x80, m4)
9680 | | }
9681 | | }
9682 | |
9683 | | function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
9684 | | bytes32 m0;
9685 | | bytes32 m1;
9686 | | bytes32 m2;
9687 | | bytes32 m3;
9688 | | bytes32 m4;
9689 | | /// @solidity memory-safe-assembly
9690 | | assembly {
9691 | | m0 := mload(0x00)
9692 | | m1 := mload(0x20)
9693 | | m2 := mload(0x40)
9694 | | m3 := mload(0x60)
9695 | | m4 := mload(0x80)
9696 | | // Selector of `log(uint256,uint256,uint256,uint256)`.
9697 | | mstore(0x00, 0x193fb800)
9698 | | mstore(0x20, p0)
9699 | | mstore(0x40, p1)
9700 | | mstore(0x60, p2)
9701 | | mstore(0x80, p3)
9702 | | }
9703 | | _sendLogPayload(0x1c, 0x84);
9704 | | /// @solidity memory-safe-assembly
9705 | | assembly {
9706 | | mstore(0x00, m0)
9707 | | mstore(0x20, m1)
9708 | | mstore(0x40, m2)
9709 | | mstore(0x60, m3)
9710 | | mstore(0x80, m4)
9711 | | }
9712 | | }
9713 | |
9714 | | function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
9715 | | bytes32 m0;
9716 | | bytes32 m1;
9717 | | bytes32 m2;
9718 | | bytes32 m3;
9719 | | bytes32 m4;
9720 | | bytes32 m5;
9721 | | bytes32 m6;
9722 | | /// @solidity memory-safe-assembly
9723 | | assembly {
9724 | | function writeString(pos, w) {
9725 | | let length := 0
9726 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9727 | | mstore(pos, length)
9728 | | let shift := sub(256, shl(3, length))
9729 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9730 | | }
9731 | | m0 := mload(0x00)
9732 | | m1 := mload(0x20)
9733 | | m2 := mload(0x40)
9734 | | m3 := mload(0x60)
9735 | | m4 := mload(0x80)
9736 | | m5 := mload(0xa0)
9737 | | m6 := mload(0xc0)
9738 | | // Selector of `log(uint256,uint256,uint256,string)`.
9739 | | mstore(0x00, 0x59cfcbe3)
9740 | | mstore(0x20, p0)
9741 | | mstore(0x40, p1)
9742 | | mstore(0x60, p2)
9743 | | mstore(0x80, 0x80)
9744 | | writeString(0xa0, p3)
9745 | | }
9746 | | _sendLogPayload(0x1c, 0xc4);
9747 | | /// @solidity memory-safe-assembly
9748 | | assembly {
9749 | | mstore(0x00, m0)
9750 | | mstore(0x20, m1)
9751 | | mstore(0x40, m2)
9752 | | mstore(0x60, m3)
9753 | | mstore(0x80, m4)
9754 | | mstore(0xa0, m5)
9755 | | mstore(0xc0, m6)
9756 | | }
9757 | | }
9758 | |
9759 | | function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure {
9760 | | bytes32 m0;
9761 | | bytes32 m1;
9762 | | bytes32 m2;
9763 | | bytes32 m3;
9764 | | bytes32 m4;
9765 | | bytes32 m5;
9766 | | bytes32 m6;
9767 | | /// @solidity memory-safe-assembly
9768 | | assembly {
9769 | | function writeString(pos, w) {
9770 | | let length := 0
9771 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9772 | | mstore(pos, length)
9773 | | let shift := sub(256, shl(3, length))
9774 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9775 | | }
9776 | | m0 := mload(0x00)
9777 | | m1 := mload(0x20)
9778 | | m2 := mload(0x40)
9779 | | m3 := mload(0x60)
9780 | | m4 := mload(0x80)
9781 | | m5 := mload(0xa0)
9782 | | m6 := mload(0xc0)
9783 | | // Selector of `log(uint256,uint256,string,address)`.
9784 | | mstore(0x00, 0x42d21db7)
9785 | | mstore(0x20, p0)
9786 | | mstore(0x40, p1)
9787 | | mstore(0x60, 0x80)
9788 | | mstore(0x80, p3)
9789 | | writeString(0xa0, p2)
9790 | | }
9791 | | _sendLogPayload(0x1c, 0xc4);
9792 | | /// @solidity memory-safe-assembly
9793 | | assembly {
9794 | | mstore(0x00, m0)
9795 | | mstore(0x20, m1)
9796 | | mstore(0x40, m2)
9797 | | mstore(0x60, m3)
9798 | | mstore(0x80, m4)
9799 | | mstore(0xa0, m5)
9800 | | mstore(0xc0, m6)
9801 | | }
9802 | | }
9803 | |
9804 | | function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
9805 | | bytes32 m0;
9806 | | bytes32 m1;
9807 | | bytes32 m2;
9808 | | bytes32 m3;
9809 | | bytes32 m4;
9810 | | bytes32 m5;
9811 | | bytes32 m6;
9812 | | /// @solidity memory-safe-assembly
9813 | | assembly {
9814 | | function writeString(pos, w) {
9815 | | let length := 0
9816 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9817 | | mstore(pos, length)
9818 | | let shift := sub(256, shl(3, length))
9819 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9820 | | }
9821 | | m0 := mload(0x00)
9822 | | m1 := mload(0x20)
9823 | | m2 := mload(0x40)
9824 | | m3 := mload(0x60)
9825 | | m4 := mload(0x80)
9826 | | m5 := mload(0xa0)
9827 | | m6 := mload(0xc0)
9828 | | // Selector of `log(uint256,uint256,string,bool)`.
9829 | | mstore(0x00, 0x7af6ab25)
9830 | | mstore(0x20, p0)
9831 | | mstore(0x40, p1)
9832 | | mstore(0x60, 0x80)
9833 | | mstore(0x80, p3)
9834 | | writeString(0xa0, p2)
9835 | | }
9836 | | _sendLogPayload(0x1c, 0xc4);
9837 | | /// @solidity memory-safe-assembly
9838 | | assembly {
9839 | | mstore(0x00, m0)
9840 | | mstore(0x20, m1)
9841 | | mstore(0x40, m2)
9842 | | mstore(0x60, m3)
9843 | | mstore(0x80, m4)
9844 | | mstore(0xa0, m5)
9845 | | mstore(0xc0, m6)
9846 | | }
9847 | | }
9848 | |
9849 | | function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
9850 | | bytes32 m0;
9851 | | bytes32 m1;
9852 | | bytes32 m2;
9853 | | bytes32 m3;
9854 | | bytes32 m4;
9855 | | bytes32 m5;
9856 | | bytes32 m6;
9857 | | /// @solidity memory-safe-assembly
9858 | | assembly {
9859 | | function writeString(pos, w) {
9860 | | let length := 0
9861 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9862 | | mstore(pos, length)
9863 | | let shift := sub(256, shl(3, length))
9864 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9865 | | }
9866 | | m0 := mload(0x00)
9867 | | m1 := mload(0x20)
9868 | | m2 := mload(0x40)
9869 | | m3 := mload(0x60)
9870 | | m4 := mload(0x80)
9871 | | m5 := mload(0xa0)
9872 | | m6 := mload(0xc0)
9873 | | // Selector of `log(uint256,uint256,string,uint256)`.
9874 | | mstore(0x00, 0x5da297eb)
9875 | | mstore(0x20, p0)
9876 | | mstore(0x40, p1)
9877 | | mstore(0x60, 0x80)
9878 | | mstore(0x80, p3)
9879 | | writeString(0xa0, p2)
9880 | | }
9881 | | _sendLogPayload(0x1c, 0xc4);
9882 | | /// @solidity memory-safe-assembly
9883 | | assembly {
9884 | | mstore(0x00, m0)
9885 | | mstore(0x20, m1)
9886 | | mstore(0x40, m2)
9887 | | mstore(0x60, m3)
9888 | | mstore(0x80, m4)
9889 | | mstore(0xa0, m5)
9890 | | mstore(0xc0, m6)
9891 | | }
9892 | | }
9893 | |
9894 | | function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
9895 | | bytes32 m0;
9896 | | bytes32 m1;
9897 | | bytes32 m2;
9898 | | bytes32 m3;
9899 | | bytes32 m4;
9900 | | bytes32 m5;
9901 | | bytes32 m6;
9902 | | bytes32 m7;
9903 | | bytes32 m8;
9904 | | /// @solidity memory-safe-assembly
9905 | | assembly {
9906 | | function writeString(pos, w) {
9907 | | let length := 0
9908 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9909 | | mstore(pos, length)
9910 | | let shift := sub(256, shl(3, length))
9911 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9912 | | }
9913 | | m0 := mload(0x00)
9914 | | m1 := mload(0x20)
9915 | | m2 := mload(0x40)
9916 | | m3 := mload(0x60)
9917 | | m4 := mload(0x80)
9918 | | m5 := mload(0xa0)
9919 | | m6 := mload(0xc0)
9920 | | m7 := mload(0xe0)
9921 | | m8 := mload(0x100)
9922 | | // Selector of `log(uint256,uint256,string,string)`.
9923 | | mstore(0x00, 0x27d8afd2)
9924 | | mstore(0x20, p0)
9925 | | mstore(0x40, p1)
9926 | | mstore(0x60, 0x80)
9927 | | mstore(0x80, 0xc0)
9928 | | writeString(0xa0, p2)
9929 | | writeString(0xe0, p3)
9930 | | }
9931 | | _sendLogPayload(0x1c, 0x104);
9932 | | /// @solidity memory-safe-assembly
9933 | | assembly {
9934 | | mstore(0x00, m0)
9935 | | mstore(0x20, m1)
9936 | | mstore(0x40, m2)
9937 | | mstore(0x60, m3)
9938 | | mstore(0x80, m4)
9939 | | mstore(0xa0, m5)
9940 | | mstore(0xc0, m6)
9941 | | mstore(0xe0, m7)
9942 | | mstore(0x100, m8)
9943 | | }
9944 | | }
9945 | |
9946 | | function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure {
9947 | | bytes32 m0;
9948 | | bytes32 m1;
9949 | | bytes32 m2;
9950 | | bytes32 m3;
9951 | | bytes32 m4;
9952 | | bytes32 m5;
9953 | | bytes32 m6;
9954 | | /// @solidity memory-safe-assembly
9955 | | assembly {
9956 | | function writeString(pos, w) {
9957 | | let length := 0
9958 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9959 | | mstore(pos, length)
9960 | | let shift := sub(256, shl(3, length))
9961 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9962 | | }
9963 | | m0 := mload(0x00)
9964 | | m1 := mload(0x20)
9965 | | m2 := mload(0x40)
9966 | | m3 := mload(0x60)
9967 | | m4 := mload(0x80)
9968 | | m5 := mload(0xa0)
9969 | | m6 := mload(0xc0)
9970 | | // Selector of `log(uint256,string,address,address)`.
9971 | | mstore(0x00, 0x6168ed61)
9972 | | mstore(0x20, p0)
9973 | | mstore(0x40, 0x80)
9974 | | mstore(0x60, p2)
9975 | | mstore(0x80, p3)
9976 | | writeString(0xa0, p1)
9977 | | }
9978 | | _sendLogPayload(0x1c, 0xc4);
9979 | | /// @solidity memory-safe-assembly
9980 | | assembly {
9981 | | mstore(0x00, m0)
9982 | | mstore(0x20, m1)
9983 | | mstore(0x40, m2)
9984 | | mstore(0x60, m3)
9985 | | mstore(0x80, m4)
9986 | | mstore(0xa0, m5)
9987 | | mstore(0xc0, m6)
9988 | | }
9989 | | }
9990 | |
9991 | | function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure {
9992 | | bytes32 m0;
9993 | | bytes32 m1;
9994 | | bytes32 m2;
9995 | | bytes32 m3;
9996 | | bytes32 m4;
9997 | | bytes32 m5;
9998 | | bytes32 m6;
9999 | | /// @solidity memory-safe-assembly
10000 | | assembly {
10001 | | function writeString(pos, w) {
10002 | | let length := 0
10003 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10004 | | mstore(pos, length)
10005 | | let shift := sub(256, shl(3, length))
10006 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10007 | | }
10008 | | m0 := mload(0x00)
10009 | | m1 := mload(0x20)
10010 | | m2 := mload(0x40)
10011 | | m3 := mload(0x60)
10012 | | m4 := mload(0x80)
10013 | | m5 := mload(0xa0)
10014 | | m6 := mload(0xc0)
10015 | | // Selector of `log(uint256,string,address,bool)`.
10016 | | mstore(0x00, 0x90c30a56)
10017 | | mstore(0x20, p0)
10018 | | mstore(0x40, 0x80)
10019 | | mstore(0x60, p2)
10020 | | mstore(0x80, p3)
10021 | | writeString(0xa0, p1)
10022 | | }
10023 | | _sendLogPayload(0x1c, 0xc4);
10024 | | /// @solidity memory-safe-assembly
10025 | | assembly {
10026 | | mstore(0x00, m0)
10027 | | mstore(0x20, m1)
10028 | | mstore(0x40, m2)
10029 | | mstore(0x60, m3)
10030 | | mstore(0x80, m4)
10031 | | mstore(0xa0, m5)
10032 | | mstore(0xc0, m6)
10033 | | }
10034 | | }
10035 | |
10036 | | function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure {
10037 | | bytes32 m0;
10038 | | bytes32 m1;
10039 | | bytes32 m2;
10040 | | bytes32 m3;
10041 | | bytes32 m4;
10042 | | bytes32 m5;
10043 | | bytes32 m6;
10044 | | /// @solidity memory-safe-assembly
10045 | | assembly {
10046 | | function writeString(pos, w) {
10047 | | let length := 0
10048 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10049 | | mstore(pos, length)
10050 | | let shift := sub(256, shl(3, length))
10051 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10052 | | }
10053 | | m0 := mload(0x00)
10054 | | m1 := mload(0x20)
10055 | | m2 := mload(0x40)
10056 | | m3 := mload(0x60)
10057 | | m4 := mload(0x80)
10058 | | m5 := mload(0xa0)
10059 | | m6 := mload(0xc0)
10060 | | // Selector of `log(uint256,string,address,uint256)`.
10061 | | mstore(0x00, 0xe8d3018d)
10062 | | mstore(0x20, p0)
10063 | | mstore(0x40, 0x80)
10064 | | mstore(0x60, p2)
10065 | | mstore(0x80, p3)
10066 | | writeString(0xa0, p1)
10067 | | }
10068 | | _sendLogPayload(0x1c, 0xc4);
10069 | | /// @solidity memory-safe-assembly
10070 | | assembly {
10071 | | mstore(0x00, m0)
10072 | | mstore(0x20, m1)
10073 | | mstore(0x40, m2)
10074 | | mstore(0x60, m3)
10075 | | mstore(0x80, m4)
10076 | | mstore(0xa0, m5)
10077 | | mstore(0xc0, m6)
10078 | | }
10079 | | }
10080 | |
10081 | | function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
10082 | | bytes32 m0;
10083 | | bytes32 m1;
10084 | | bytes32 m2;
10085 | | bytes32 m3;
10086 | | bytes32 m4;
10087 | | bytes32 m5;
10088 | | bytes32 m6;
10089 | | bytes32 m7;
10090 | | bytes32 m8;
10091 | | /// @solidity memory-safe-assembly
10092 | | assembly {
10093 | | function writeString(pos, w) {
10094 | | let length := 0
10095 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10096 | | mstore(pos, length)
10097 | | let shift := sub(256, shl(3, length))
10098 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10099 | | }
10100 | | m0 := mload(0x00)
10101 | | m1 := mload(0x20)
10102 | | m2 := mload(0x40)
10103 | | m3 := mload(0x60)
10104 | | m4 := mload(0x80)
10105 | | m5 := mload(0xa0)
10106 | | m6 := mload(0xc0)
10107 | | m7 := mload(0xe0)
10108 | | m8 := mload(0x100)
10109 | | // Selector of `log(uint256,string,address,string)`.
10110 | | mstore(0x00, 0x9c3adfa1)
10111 | | mstore(0x20, p0)
10112 | | mstore(0x40, 0x80)
10113 | | mstore(0x60, p2)
10114 | | mstore(0x80, 0xc0)
10115 | | writeString(0xa0, p1)
10116 | | writeString(0xe0, p3)
10117 | | }
10118 | | _sendLogPayload(0x1c, 0x104);
10119 | | /// @solidity memory-safe-assembly
10120 | | assembly {
10121 | | mstore(0x00, m0)
10122 | | mstore(0x20, m1)
10123 | | mstore(0x40, m2)
10124 | | mstore(0x60, m3)
10125 | | mstore(0x80, m4)
10126 | | mstore(0xa0, m5)
10127 | | mstore(0xc0, m6)
10128 | | mstore(0xe0, m7)
10129 | | mstore(0x100, m8)
10130 | | }
10131 | | }
10132 | |
10133 | | function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure {
10134 | | bytes32 m0;
10135 | | bytes32 m1;
10136 | | bytes32 m2;
10137 | | bytes32 m3;
10138 | | bytes32 m4;
10139 | | bytes32 m5;
10140 | | bytes32 m6;
10141 | | /// @solidity memory-safe-assembly
10142 | | assembly {
10143 | | function writeString(pos, w) {
10144 | | let length := 0
10145 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10146 | | mstore(pos, length)
10147 | | let shift := sub(256, shl(3, length))
10148 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10149 | | }
10150 | | m0 := mload(0x00)
10151 | | m1 := mload(0x20)
10152 | | m2 := mload(0x40)
10153 | | m3 := mload(0x60)
10154 | | m4 := mload(0x80)
10155 | | m5 := mload(0xa0)
10156 | | m6 := mload(0xc0)
10157 | | // Selector of `log(uint256,string,bool,address)`.
10158 | | mstore(0x00, 0xae2ec581)
10159 | | mstore(0x20, p0)
10160 | | mstore(0x40, 0x80)
10161 | | mstore(0x60, p2)
10162 | | mstore(0x80, p3)
10163 | | writeString(0xa0, p1)
10164 | | }
10165 | | _sendLogPayload(0x1c, 0xc4);
10166 | | /// @solidity memory-safe-assembly
10167 | | assembly {
10168 | | mstore(0x00, m0)
10169 | | mstore(0x20, m1)
10170 | | mstore(0x40, m2)
10171 | | mstore(0x60, m3)
10172 | | mstore(0x80, m4)
10173 | | mstore(0xa0, m5)
10174 | | mstore(0xc0, m6)
10175 | | }
10176 | | }
10177 | |
10178 | | function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure {
10179 | | bytes32 m0;
10180 | | bytes32 m1;
10181 | | bytes32 m2;
10182 | | bytes32 m3;
10183 | | bytes32 m4;
10184 | | bytes32 m5;
10185 | | bytes32 m6;
10186 | | /// @solidity memory-safe-assembly
10187 | | assembly {
10188 | | function writeString(pos, w) {
10189 | | let length := 0
10190 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10191 | | mstore(pos, length)
10192 | | let shift := sub(256, shl(3, length))
10193 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10194 | | }
10195 | | m0 := mload(0x00)
10196 | | m1 := mload(0x20)
10197 | | m2 := mload(0x40)
10198 | | m3 := mload(0x60)
10199 | | m4 := mload(0x80)
10200 | | m5 := mload(0xa0)
10201 | | m6 := mload(0xc0)
10202 | | // Selector of `log(uint256,string,bool,bool)`.
10203 | | mstore(0x00, 0xba535d9c)
10204 | | mstore(0x20, p0)
10205 | | mstore(0x40, 0x80)
10206 | | mstore(0x60, p2)
10207 | | mstore(0x80, p3)
10208 | | writeString(0xa0, p1)
10209 | | }
10210 | | _sendLogPayload(0x1c, 0xc4);
10211 | | /// @solidity memory-safe-assembly
10212 | | assembly {
10213 | | mstore(0x00, m0)
10214 | | mstore(0x20, m1)
10215 | | mstore(0x40, m2)
10216 | | mstore(0x60, m3)
10217 | | mstore(0x80, m4)
10218 | | mstore(0xa0, m5)
10219 | | mstore(0xc0, m6)
10220 | | }
10221 | | }
10222 | |
10223 | | function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
10224 | | bytes32 m0;
10225 | | bytes32 m1;
10226 | | bytes32 m2;
10227 | | bytes32 m3;
10228 | | bytes32 m4;
10229 | | bytes32 m5;
10230 | | bytes32 m6;
10231 | | /// @solidity memory-safe-assembly
10232 | | assembly {
10233 | | function writeString(pos, w) {
10234 | | let length := 0
10235 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10236 | | mstore(pos, length)
10237 | | let shift := sub(256, shl(3, length))
10238 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10239 | | }
10240 | | m0 := mload(0x00)
10241 | | m1 := mload(0x20)
10242 | | m2 := mload(0x40)
10243 | | m3 := mload(0x60)
10244 | | m4 := mload(0x80)
10245 | | m5 := mload(0xa0)
10246 | | m6 := mload(0xc0)
10247 | | // Selector of `log(uint256,string,bool,uint256)`.
10248 | | mstore(0x00, 0xcf009880)
10249 | | mstore(0x20, p0)
10250 | | mstore(0x40, 0x80)
10251 | | mstore(0x60, p2)
10252 | | mstore(0x80, p3)
10253 | | writeString(0xa0, p1)
10254 | | }
10255 | | _sendLogPayload(0x1c, 0xc4);
10256 | | /// @solidity memory-safe-assembly
10257 | | assembly {
10258 | | mstore(0x00, m0)
10259 | | mstore(0x20, m1)
10260 | | mstore(0x40, m2)
10261 | | mstore(0x60, m3)
10262 | | mstore(0x80, m4)
10263 | | mstore(0xa0, m5)
10264 | | mstore(0xc0, m6)
10265 | | }
10266 | | }
10267 | |
10268 | | function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
10269 | | bytes32 m0;
10270 | | bytes32 m1;
10271 | | bytes32 m2;
10272 | | bytes32 m3;
10273 | | bytes32 m4;
10274 | | bytes32 m5;
10275 | | bytes32 m6;
10276 | | bytes32 m7;
10277 | | bytes32 m8;
10278 | | /// @solidity memory-safe-assembly
10279 | | assembly {
10280 | | function writeString(pos, w) {
10281 | | let length := 0
10282 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10283 | | mstore(pos, length)
10284 | | let shift := sub(256, shl(3, length))
10285 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10286 | | }
10287 | | m0 := mload(0x00)
10288 | | m1 := mload(0x20)
10289 | | m2 := mload(0x40)
10290 | | m3 := mload(0x60)
10291 | | m4 := mload(0x80)
10292 | | m5 := mload(0xa0)
10293 | | m6 := mload(0xc0)
10294 | | m7 := mload(0xe0)
10295 | | m8 := mload(0x100)
10296 | | // Selector of `log(uint256,string,bool,string)`.
10297 | | mstore(0x00, 0xd2d423cd)
10298 | | mstore(0x20, p0)
10299 | | mstore(0x40, 0x80)
10300 | | mstore(0x60, p2)
10301 | | mstore(0x80, 0xc0)
10302 | | writeString(0xa0, p1)
10303 | | writeString(0xe0, p3)
10304 | | }
10305 | | _sendLogPayload(0x1c, 0x104);
10306 | | /// @solidity memory-safe-assembly
10307 | | assembly {
10308 | | mstore(0x00, m0)
10309 | | mstore(0x20, m1)
10310 | | mstore(0x40, m2)
10311 | | mstore(0x60, m3)
10312 | | mstore(0x80, m4)
10313 | | mstore(0xa0, m5)
10314 | | mstore(0xc0, m6)
10315 | | mstore(0xe0, m7)
10316 | | mstore(0x100, m8)
10317 | | }
10318 | | }
10319 | |
10320 | | function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure {
10321 | | bytes32 m0;
10322 | | bytes32 m1;
10323 | | bytes32 m2;
10324 | | bytes32 m3;
10325 | | bytes32 m4;
10326 | | bytes32 m5;
10327 | | bytes32 m6;
10328 | | /// @solidity memory-safe-assembly
10329 | | assembly {
10330 | | function writeString(pos, w) {
10331 | | let length := 0
10332 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10333 | | mstore(pos, length)
10334 | | let shift := sub(256, shl(3, length))
10335 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10336 | | }
10337 | | m0 := mload(0x00)
10338 | | m1 := mload(0x20)
10339 | | m2 := mload(0x40)
10340 | | m3 := mload(0x60)
10341 | | m4 := mload(0x80)
10342 | | m5 := mload(0xa0)
10343 | | m6 := mload(0xc0)
10344 | | // Selector of `log(uint256,string,uint256,address)`.
10345 | | mstore(0x00, 0x3b2279b4)
10346 | | mstore(0x20, p0)
10347 | | mstore(0x40, 0x80)
10348 | | mstore(0x60, p2)
10349 | | mstore(0x80, p3)
10350 | | writeString(0xa0, p1)
10351 | | }
10352 | | _sendLogPayload(0x1c, 0xc4);
10353 | | /// @solidity memory-safe-assembly
10354 | | assembly {
10355 | | mstore(0x00, m0)
10356 | | mstore(0x20, m1)
10357 | | mstore(0x40, m2)
10358 | | mstore(0x60, m3)
10359 | | mstore(0x80, m4)
10360 | | mstore(0xa0, m5)
10361 | | mstore(0xc0, m6)
10362 | | }
10363 | | }
10364 | |
10365 | | function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
10366 | | bytes32 m0;
10367 | | bytes32 m1;
10368 | | bytes32 m2;
10369 | | bytes32 m3;
10370 | | bytes32 m4;
10371 | | bytes32 m5;
10372 | | bytes32 m6;
10373 | | /// @solidity memory-safe-assembly
10374 | | assembly {
10375 | | function writeString(pos, w) {
10376 | | let length := 0
10377 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10378 | | mstore(pos, length)
10379 | | let shift := sub(256, shl(3, length))
10380 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10381 | | }
10382 | | m0 := mload(0x00)
10383 | | m1 := mload(0x20)
10384 | | m2 := mload(0x40)
10385 | | m3 := mload(0x60)
10386 | | m4 := mload(0x80)
10387 | | m5 := mload(0xa0)
10388 | | m6 := mload(0xc0)
10389 | | // Selector of `log(uint256,string,uint256,bool)`.
10390 | | mstore(0x00, 0x691a8f74)
10391 | | mstore(0x20, p0)
10392 | | mstore(0x40, 0x80)
10393 | | mstore(0x60, p2)
10394 | | mstore(0x80, p3)
10395 | | writeString(0xa0, p1)
10396 | | }
10397 | | _sendLogPayload(0x1c, 0xc4);
10398 | | /// @solidity memory-safe-assembly
10399 | | assembly {
10400 | | mstore(0x00, m0)
10401 | | mstore(0x20, m1)
10402 | | mstore(0x40, m2)
10403 | | mstore(0x60, m3)
10404 | | mstore(0x80, m4)
10405 | | mstore(0xa0, m5)
10406 | | mstore(0xc0, m6)
10407 | | }
10408 | | }
10409 | |
10410 | | function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
10411 | | bytes32 m0;
10412 | | bytes32 m1;
10413 | | bytes32 m2;
10414 | | bytes32 m3;
10415 | | bytes32 m4;
10416 | | bytes32 m5;
10417 | | bytes32 m6;
10418 | | /// @solidity memory-safe-assembly
10419 | | assembly {
10420 | | function writeString(pos, w) {
10421 | | let length := 0
10422 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10423 | | mstore(pos, length)
10424 | | let shift := sub(256, shl(3, length))
10425 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10426 | | }
10427 | | m0 := mload(0x00)
10428 | | m1 := mload(0x20)
10429 | | m2 := mload(0x40)
10430 | | m3 := mload(0x60)
10431 | | m4 := mload(0x80)
10432 | | m5 := mload(0xa0)
10433 | | m6 := mload(0xc0)
10434 | | // Selector of `log(uint256,string,uint256,uint256)`.
10435 | | mstore(0x00, 0x82c25b74)
10436 | | mstore(0x20, p0)
10437 | | mstore(0x40, 0x80)
10438 | | mstore(0x60, p2)
10439 | | mstore(0x80, p3)
10440 | | writeString(0xa0, p1)
10441 | | }
10442 | | _sendLogPayload(0x1c, 0xc4);
10443 | | /// @solidity memory-safe-assembly
10444 | | assembly {
10445 | | mstore(0x00, m0)
10446 | | mstore(0x20, m1)
10447 | | mstore(0x40, m2)
10448 | | mstore(0x60, m3)
10449 | | mstore(0x80, m4)
10450 | | mstore(0xa0, m5)
10451 | | mstore(0xc0, m6)
10452 | | }
10453 | | }
10454 | |
10455 | | function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
10456 | | bytes32 m0;
10457 | | bytes32 m1;
10458 | | bytes32 m2;
10459 | | bytes32 m3;
10460 | | bytes32 m4;
10461 | | bytes32 m5;
10462 | | bytes32 m6;
10463 | | bytes32 m7;
10464 | | bytes32 m8;
10465 | | /// @solidity memory-safe-assembly
10466 | | assembly {
10467 | | function writeString(pos, w) {
10468 | | let length := 0
10469 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10470 | | mstore(pos, length)
10471 | | let shift := sub(256, shl(3, length))
10472 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10473 | | }
10474 | | m0 := mload(0x00)
10475 | | m1 := mload(0x20)
10476 | | m2 := mload(0x40)
10477 | | m3 := mload(0x60)
10478 | | m4 := mload(0x80)
10479 | | m5 := mload(0xa0)
10480 | | m6 := mload(0xc0)
10481 | | m7 := mload(0xe0)
10482 | | m8 := mload(0x100)
10483 | | // Selector of `log(uint256,string,uint256,string)`.
10484 | | mstore(0x00, 0xb7b914ca)
10485 | | mstore(0x20, p0)
10486 | | mstore(0x40, 0x80)
10487 | | mstore(0x60, p2)
10488 | | mstore(0x80, 0xc0)
10489 | | writeString(0xa0, p1)
10490 | | writeString(0xe0, p3)
10491 | | }
10492 | | _sendLogPayload(0x1c, 0x104);
10493 | | /// @solidity memory-safe-assembly
10494 | | assembly {
10495 | | mstore(0x00, m0)
10496 | | mstore(0x20, m1)
10497 | | mstore(0x40, m2)
10498 | | mstore(0x60, m3)
10499 | | mstore(0x80, m4)
10500 | | mstore(0xa0, m5)
10501 | | mstore(0xc0, m6)
10502 | | mstore(0xe0, m7)
10503 | | mstore(0x100, m8)
10504 | | }
10505 | | }
10506 | |
10507 | | function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
10508 | | bytes32 m0;
10509 | | bytes32 m1;
10510 | | bytes32 m2;
10511 | | bytes32 m3;
10512 | | bytes32 m4;
10513 | | bytes32 m5;
10514 | | bytes32 m6;
10515 | | bytes32 m7;
10516 | | bytes32 m8;
10517 | | /// @solidity memory-safe-assembly
10518 | | assembly {
10519 | | function writeString(pos, w) {
10520 | | let length := 0
10521 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10522 | | mstore(pos, length)
10523 | | let shift := sub(256, shl(3, length))
10524 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10525 | | }
10526 | | m0 := mload(0x00)
10527 | | m1 := mload(0x20)
10528 | | m2 := mload(0x40)
10529 | | m3 := mload(0x60)
10530 | | m4 := mload(0x80)
10531 | | m5 := mload(0xa0)
10532 | | m6 := mload(0xc0)
10533 | | m7 := mload(0xe0)
10534 | | m8 := mload(0x100)
10535 | | // Selector of `log(uint256,string,string,address)`.
10536 | | mstore(0x00, 0xd583c602)
10537 | | mstore(0x20, p0)
10538 | | mstore(0x40, 0x80)
10539 | | mstore(0x60, 0xc0)
10540 | | mstore(0x80, p3)
10541 | | writeString(0xa0, p1)
10542 | | writeString(0xe0, p2)
10543 | | }
10544 | | _sendLogPayload(0x1c, 0x104);
10545 | | /// @solidity memory-safe-assembly
10546 | | assembly {
10547 | | mstore(0x00, m0)
10548 | | mstore(0x20, m1)
10549 | | mstore(0x40, m2)
10550 | | mstore(0x60, m3)
10551 | | mstore(0x80, m4)
10552 | | mstore(0xa0, m5)
10553 | | mstore(0xc0, m6)
10554 | | mstore(0xe0, m7)
10555 | | mstore(0x100, m8)
10556 | | }
10557 | | }
10558 | |
10559 | | function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
10560 | | bytes32 m0;
10561 | | bytes32 m1;
10562 | | bytes32 m2;
10563 | | bytes32 m3;
10564 | | bytes32 m4;
10565 | | bytes32 m5;
10566 | | bytes32 m6;
10567 | | bytes32 m7;
10568 | | bytes32 m8;
10569 | | /// @solidity memory-safe-assembly
10570 | | assembly {
10571 | | function writeString(pos, w) {
10572 | | let length := 0
10573 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10574 | | mstore(pos, length)
10575 | | let shift := sub(256, shl(3, length))
10576 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10577 | | }
10578 | | m0 := mload(0x00)
10579 | | m1 := mload(0x20)
10580 | | m2 := mload(0x40)
10581 | | m3 := mload(0x60)
10582 | | m4 := mload(0x80)
10583 | | m5 := mload(0xa0)
10584 | | m6 := mload(0xc0)
10585 | | m7 := mload(0xe0)
10586 | | m8 := mload(0x100)
10587 | | // Selector of `log(uint256,string,string,bool)`.
10588 | | mstore(0x00, 0xb3a6b6bd)
10589 | | mstore(0x20, p0)
10590 | | mstore(0x40, 0x80)
10591 | | mstore(0x60, 0xc0)
10592 | | mstore(0x80, p3)
10593 | | writeString(0xa0, p1)
10594 | | writeString(0xe0, p2)
10595 | | }
10596 | | _sendLogPayload(0x1c, 0x104);
10597 | | /// @solidity memory-safe-assembly
10598 | | assembly {
10599 | | mstore(0x00, m0)
10600 | | mstore(0x20, m1)
10601 | | mstore(0x40, m2)
10602 | | mstore(0x60, m3)
10603 | | mstore(0x80, m4)
10604 | | mstore(0xa0, m5)
10605 | | mstore(0xc0, m6)
10606 | | mstore(0xe0, m7)
10607 | | mstore(0x100, m8)
10608 | | }
10609 | | }
10610 | |
10611 | | function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
10612 | | bytes32 m0;
10613 | | bytes32 m1;
10614 | | bytes32 m2;
10615 | | bytes32 m3;
10616 | | bytes32 m4;
10617 | | bytes32 m5;
10618 | | bytes32 m6;
10619 | | bytes32 m7;
10620 | | bytes32 m8;
10621 | | /// @solidity memory-safe-assembly
10622 | | assembly {
10623 | | function writeString(pos, w) {
10624 | | let length := 0
10625 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10626 | | mstore(pos, length)
10627 | | let shift := sub(256, shl(3, length))
10628 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10629 | | }
10630 | | m0 := mload(0x00)
10631 | | m1 := mload(0x20)
10632 | | m2 := mload(0x40)
10633 | | m3 := mload(0x60)
10634 | | m4 := mload(0x80)
10635 | | m5 := mload(0xa0)
10636 | | m6 := mload(0xc0)
10637 | | m7 := mload(0xe0)
10638 | | m8 := mload(0x100)
10639 | | // Selector of `log(uint256,string,string,uint256)`.
10640 | | mstore(0x00, 0xb028c9bd)
10641 | | mstore(0x20, p0)
10642 | | mstore(0x40, 0x80)
10643 | | mstore(0x60, 0xc0)
10644 | | mstore(0x80, p3)
10645 | | writeString(0xa0, p1)
10646 | | writeString(0xe0, p2)
10647 | | }
10648 | | _sendLogPayload(0x1c, 0x104);
10649 | | /// @solidity memory-safe-assembly
10650 | | assembly {
10651 | | mstore(0x00, m0)
10652 | | mstore(0x20, m1)
10653 | | mstore(0x40, m2)
10654 | | mstore(0x60, m3)
10655 | | mstore(0x80, m4)
10656 | | mstore(0xa0, m5)
10657 | | mstore(0xc0, m6)
10658 | | mstore(0xe0, m7)
10659 | | mstore(0x100, m8)
10660 | | }
10661 | | }
10662 | |
10663 | | function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
10664 | | bytes32 m0;
10665 | | bytes32 m1;
10666 | | bytes32 m2;
10667 | | bytes32 m3;
10668 | | bytes32 m4;
10669 | | bytes32 m5;
10670 | | bytes32 m6;
10671 | | bytes32 m7;
10672 | | bytes32 m8;
10673 | | bytes32 m9;
10674 | | bytes32 m10;
10675 | | /// @solidity memory-safe-assembly
10676 | | assembly {
10677 | | function writeString(pos, w) {
10678 | | let length := 0
10679 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10680 | | mstore(pos, length)
10681 | | let shift := sub(256, shl(3, length))
10682 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10683 | | }
10684 | | m0 := mload(0x00)
10685 | | m1 := mload(0x20)
10686 | | m2 := mload(0x40)
10687 | | m3 := mload(0x60)
10688 | | m4 := mload(0x80)
10689 | | m5 := mload(0xa0)
10690 | | m6 := mload(0xc0)
10691 | | m7 := mload(0xe0)
10692 | | m8 := mload(0x100)
10693 | | m9 := mload(0x120)
10694 | | m10 := mload(0x140)
10695 | | // Selector of `log(uint256,string,string,string)`.
10696 | | mstore(0x00, 0x21ad0683)
10697 | | mstore(0x20, p0)
10698 | | mstore(0x40, 0x80)
10699 | | mstore(0x60, 0xc0)
10700 | | mstore(0x80, 0x100)
10701 | | writeString(0xa0, p1)
10702 | | writeString(0xe0, p2)
10703 | | writeString(0x120, p3)
10704 | | }
10705 | | _sendLogPayload(0x1c, 0x144);
10706 | | /// @solidity memory-safe-assembly
10707 | | assembly {
10708 | | mstore(0x00, m0)
10709 | | mstore(0x20, m1)
10710 | | mstore(0x40, m2)
10711 | | mstore(0x60, m3)
10712 | | mstore(0x80, m4)
10713 | | mstore(0xa0, m5)
10714 | | mstore(0xc0, m6)
10715 | | mstore(0xe0, m7)
10716 | | mstore(0x100, m8)
10717 | | mstore(0x120, m9)
10718 | | mstore(0x140, m10)
10719 | | }
10720 | | }
10721 | |
10722 | | function log(bytes32 p0, address p1, address p2, address p3) internal pure {
10723 | | bytes32 m0;
10724 | | bytes32 m1;
10725 | | bytes32 m2;
10726 | | bytes32 m3;
10727 | | bytes32 m4;
10728 | | bytes32 m5;
10729 | | bytes32 m6;
10730 | | /// @solidity memory-safe-assembly
10731 | | assembly {
10732 | | function writeString(pos, w) {
10733 | | let length := 0
10734 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10735 | | mstore(pos, length)
10736 | | let shift := sub(256, shl(3, length))
10737 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10738 | | }
10739 | | m0 := mload(0x00)
10740 | | m1 := mload(0x20)
10741 | | m2 := mload(0x40)
10742 | | m3 := mload(0x60)
10743 | | m4 := mload(0x80)
10744 | | m5 := mload(0xa0)
10745 | | m6 := mload(0xc0)
10746 | | // Selector of `log(string,address,address,address)`.
10747 | | mstore(0x00, 0xed8f28f6)
10748 | | mstore(0x20, 0x80)
10749 | | mstore(0x40, p1)
10750 | | mstore(0x60, p2)
10751 | | mstore(0x80, p3)
10752 | | writeString(0xa0, p0)
10753 | | }
10754 | | _sendLogPayload(0x1c, 0xc4);
10755 | | /// @solidity memory-safe-assembly
10756 | | assembly {
10757 | | mstore(0x00, m0)
10758 | | mstore(0x20, m1)
10759 | | mstore(0x40, m2)
10760 | | mstore(0x60, m3)
10761 | | mstore(0x80, m4)
10762 | | mstore(0xa0, m5)
10763 | | mstore(0xc0, m6)
10764 | | }
10765 | | }
10766 | |
10767 | | function log(bytes32 p0, address p1, address p2, bool p3) internal pure {
10768 | | bytes32 m0;
10769 | | bytes32 m1;
10770 | | bytes32 m2;
10771 | | bytes32 m3;
10772 | | bytes32 m4;
10773 | | bytes32 m5;
10774 | | bytes32 m6;
10775 | | /// @solidity memory-safe-assembly
10776 | | assembly {
10777 | | function writeString(pos, w) {
10778 | | let length := 0
10779 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10780 | | mstore(pos, length)
10781 | | let shift := sub(256, shl(3, length))
10782 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10783 | | }
10784 | | m0 := mload(0x00)
10785 | | m1 := mload(0x20)
10786 | | m2 := mload(0x40)
10787 | | m3 := mload(0x60)
10788 | | m4 := mload(0x80)
10789 | | m5 := mload(0xa0)
10790 | | m6 := mload(0xc0)
10791 | | // Selector of `log(string,address,address,bool)`.
10792 | | mstore(0x00, 0xb59dbd60)
10793 | | mstore(0x20, 0x80)
10794 | | mstore(0x40, p1)
10795 | | mstore(0x60, p2)
10796 | | mstore(0x80, p3)
10797 | | writeString(0xa0, p0)
10798 | | }
10799 | | _sendLogPayload(0x1c, 0xc4);
10800 | | /// @solidity memory-safe-assembly
10801 | | assembly {
10802 | | mstore(0x00, m0)
10803 | | mstore(0x20, m1)
10804 | | mstore(0x40, m2)
10805 | | mstore(0x60, m3)
10806 | | mstore(0x80, m4)
10807 | | mstore(0xa0, m5)
10808 | | mstore(0xc0, m6)
10809 | | }
10810 | | }
10811 | |
10812 | | function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure {
10813 | | bytes32 m0;
10814 | | bytes32 m1;
10815 | | bytes32 m2;
10816 | | bytes32 m3;
10817 | | bytes32 m4;
10818 | | bytes32 m5;
10819 | | bytes32 m6;
10820 | | /// @solidity memory-safe-assembly
10821 | | assembly {
10822 | | function writeString(pos, w) {
10823 | | let length := 0
10824 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10825 | | mstore(pos, length)
10826 | | let shift := sub(256, shl(3, length))
10827 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10828 | | }
10829 | | m0 := mload(0x00)
10830 | | m1 := mload(0x20)
10831 | | m2 := mload(0x40)
10832 | | m3 := mload(0x60)
10833 | | m4 := mload(0x80)
10834 | | m5 := mload(0xa0)
10835 | | m6 := mload(0xc0)
10836 | | // Selector of `log(string,address,address,uint256)`.
10837 | | mstore(0x00, 0x8ef3f399)
10838 | | mstore(0x20, 0x80)
10839 | | mstore(0x40, p1)
10840 | | mstore(0x60, p2)
10841 | | mstore(0x80, p3)
10842 | | writeString(0xa0, p0)
10843 | | }
10844 | | _sendLogPayload(0x1c, 0xc4);
10845 | | /// @solidity memory-safe-assembly
10846 | | assembly {
10847 | | mstore(0x00, m0)
10848 | | mstore(0x20, m1)
10849 | | mstore(0x40, m2)
10850 | | mstore(0x60, m3)
10851 | | mstore(0x80, m4)
10852 | | mstore(0xa0, m5)
10853 | | mstore(0xc0, m6)
10854 | | }
10855 | | }
10856 | |
10857 | | function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure {
10858 | | bytes32 m0;
10859 | | bytes32 m1;
10860 | | bytes32 m2;
10861 | | bytes32 m3;
10862 | | bytes32 m4;
10863 | | bytes32 m5;
10864 | | bytes32 m6;
10865 | | bytes32 m7;
10866 | | bytes32 m8;
10867 | | /// @solidity memory-safe-assembly
10868 | | assembly {
10869 | | function writeString(pos, w) {
10870 | | let length := 0
10871 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10872 | | mstore(pos, length)
10873 | | let shift := sub(256, shl(3, length))
10874 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10875 | | }
10876 | | m0 := mload(0x00)
10877 | | m1 := mload(0x20)
10878 | | m2 := mload(0x40)
10879 | | m3 := mload(0x60)
10880 | | m4 := mload(0x80)
10881 | | m5 := mload(0xa0)
10882 | | m6 := mload(0xc0)
10883 | | m7 := mload(0xe0)
10884 | | m8 := mload(0x100)
10885 | | // Selector of `log(string,address,address,string)`.
10886 | | mstore(0x00, 0x800a1c67)
10887 | | mstore(0x20, 0x80)
10888 | | mstore(0x40, p1)
10889 | | mstore(0x60, p2)
10890 | | mstore(0x80, 0xc0)
10891 | | writeString(0xa0, p0)
10892 | | writeString(0xe0, p3)
10893 | | }
10894 | | _sendLogPayload(0x1c, 0x104);
10895 | | /// @solidity memory-safe-assembly
10896 | | assembly {
10897 | | mstore(0x00, m0)
10898 | | mstore(0x20, m1)
10899 | | mstore(0x40, m2)
10900 | | mstore(0x60, m3)
10901 | | mstore(0x80, m4)
10902 | | mstore(0xa0, m5)
10903 | | mstore(0xc0, m6)
10904 | | mstore(0xe0, m7)
10905 | | mstore(0x100, m8)
10906 | | }
10907 | | }
10908 | |
10909 | | function log(bytes32 p0, address p1, bool p2, address p3) internal pure {
10910 | | bytes32 m0;
10911 | | bytes32 m1;
10912 | | bytes32 m2;
10913 | | bytes32 m3;
10914 | | bytes32 m4;
10915 | | bytes32 m5;
10916 | | bytes32 m6;
10917 | | /// @solidity memory-safe-assembly
10918 | | assembly {
10919 | | function writeString(pos, w) {
10920 | | let length := 0
10921 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10922 | | mstore(pos, length)
10923 | | let shift := sub(256, shl(3, length))
10924 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10925 | | }
10926 | | m0 := mload(0x00)
10927 | | m1 := mload(0x20)
10928 | | m2 := mload(0x40)
10929 | | m3 := mload(0x60)
10930 | | m4 := mload(0x80)
10931 | | m5 := mload(0xa0)
10932 | | m6 := mload(0xc0)
10933 | | // Selector of `log(string,address,bool,address)`.
10934 | | mstore(0x00, 0x223603bd)
10935 | | mstore(0x20, 0x80)
10936 | | mstore(0x40, p1)
10937 | | mstore(0x60, p2)
10938 | | mstore(0x80, p3)
10939 | | writeString(0xa0, p0)
10940 | | }
10941 | | _sendLogPayload(0x1c, 0xc4);
10942 | | /// @solidity memory-safe-assembly
10943 | | assembly {
10944 | | mstore(0x00, m0)
10945 | | mstore(0x20, m1)
10946 | | mstore(0x40, m2)
10947 | | mstore(0x60, m3)
10948 | | mstore(0x80, m4)
10949 | | mstore(0xa0, m5)
10950 | | mstore(0xc0, m6)
10951 | | }
10952 | | }
10953 | |
10954 | | function log(bytes32 p0, address p1, bool p2, bool p3) internal pure {
10955 | | bytes32 m0;
10956 | | bytes32 m1;
10957 | | bytes32 m2;
10958 | | bytes32 m3;
10959 | | bytes32 m4;
10960 | | bytes32 m5;
10961 | | bytes32 m6;
10962 | | /// @solidity memory-safe-assembly
10963 | | assembly {
10964 | | function writeString(pos, w) {
10965 | | let length := 0
10966 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10967 | | mstore(pos, length)
10968 | | let shift := sub(256, shl(3, length))
10969 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10970 | | }
10971 | | m0 := mload(0x00)
10972 | | m1 := mload(0x20)
10973 | | m2 := mload(0x40)
10974 | | m3 := mload(0x60)
10975 | | m4 := mload(0x80)
10976 | | m5 := mload(0xa0)
10977 | | m6 := mload(0xc0)
10978 | | // Selector of `log(string,address,bool,bool)`.
10979 | | mstore(0x00, 0x79884c2b)
10980 | | mstore(0x20, 0x80)
10981 | | mstore(0x40, p1)
10982 | | mstore(0x60, p2)
10983 | | mstore(0x80, p3)
10984 | | writeString(0xa0, p0)
10985 | | }
10986 | | _sendLogPayload(0x1c, 0xc4);
10987 | | /// @solidity memory-safe-assembly
10988 | | assembly {
10989 | | mstore(0x00, m0)
10990 | | mstore(0x20, m1)
10991 | | mstore(0x40, m2)
10992 | | mstore(0x60, m3)
10993 | | mstore(0x80, m4)
10994 | | mstore(0xa0, m5)
10995 | | mstore(0xc0, m6)
10996 | | }
10997 | | }
10998 | |
10999 | | function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure {
11000 | | bytes32 m0;
11001 | | bytes32 m1;
11002 | | bytes32 m2;
11003 | | bytes32 m3;
11004 | | bytes32 m4;
11005 | | bytes32 m5;
11006 | | bytes32 m6;
11007 | | /// @solidity memory-safe-assembly
11008 | | assembly {
11009 | | function writeString(pos, w) {
11010 | | let length := 0
11011 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11012 | | mstore(pos, length)
11013 | | let shift := sub(256, shl(3, length))
11014 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11015 | | }
11016 | | m0 := mload(0x00)
11017 | | m1 := mload(0x20)
11018 | | m2 := mload(0x40)
11019 | | m3 := mload(0x60)
11020 | | m4 := mload(0x80)
11021 | | m5 := mload(0xa0)
11022 | | m6 := mload(0xc0)
11023 | | // Selector of `log(string,address,bool,uint256)`.
11024 | | mstore(0x00, 0x3e9f866a)
11025 | | mstore(0x20, 0x80)
11026 | | mstore(0x40, p1)
11027 | | mstore(0x60, p2)
11028 | | mstore(0x80, p3)
11029 | | writeString(0xa0, p0)
11030 | | }
11031 | | _sendLogPayload(0x1c, 0xc4);
11032 | | /// @solidity memory-safe-assembly
11033 | | assembly {
11034 | | mstore(0x00, m0)
11035 | | mstore(0x20, m1)
11036 | | mstore(0x40, m2)
11037 | | mstore(0x60, m3)
11038 | | mstore(0x80, m4)
11039 | | mstore(0xa0, m5)
11040 | | mstore(0xc0, m6)
11041 | | }
11042 | | }
11043 | |
11044 | | function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure {
11045 | | bytes32 m0;
11046 | | bytes32 m1;
11047 | | bytes32 m2;
11048 | | bytes32 m3;
11049 | | bytes32 m4;
11050 | | bytes32 m5;
11051 | | bytes32 m6;
11052 | | bytes32 m7;
11053 | | bytes32 m8;
11054 | | /// @solidity memory-safe-assembly
11055 | | assembly {
11056 | | function writeString(pos, w) {
11057 | | let length := 0
11058 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11059 | | mstore(pos, length)
11060 | | let shift := sub(256, shl(3, length))
11061 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11062 | | }
11063 | | m0 := mload(0x00)
11064 | | m1 := mload(0x20)
11065 | | m2 := mload(0x40)
11066 | | m3 := mload(0x60)
11067 | | m4 := mload(0x80)
11068 | | m5 := mload(0xa0)
11069 | | m6 := mload(0xc0)
11070 | | m7 := mload(0xe0)
11071 | | m8 := mload(0x100)
11072 | | // Selector of `log(string,address,bool,string)`.
11073 | | mstore(0x00, 0x0454c079)
11074 | | mstore(0x20, 0x80)
11075 | | mstore(0x40, p1)
11076 | | mstore(0x60, p2)
11077 | | mstore(0x80, 0xc0)
11078 | | writeString(0xa0, p0)
11079 | | writeString(0xe0, p3)
11080 | | }
11081 | | _sendLogPayload(0x1c, 0x104);
11082 | | /// @solidity memory-safe-assembly
11083 | | assembly {
11084 | | mstore(0x00, m0)
11085 | | mstore(0x20, m1)
11086 | | mstore(0x40, m2)
11087 | | mstore(0x60, m3)
11088 | | mstore(0x80, m4)
11089 | | mstore(0xa0, m5)
11090 | | mstore(0xc0, m6)
11091 | | mstore(0xe0, m7)
11092 | | mstore(0x100, m8)
11093 | | }
11094 | | }
11095 | |
11096 | | function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure {
11097 | | bytes32 m0;
11098 | | bytes32 m1;
11099 | | bytes32 m2;
11100 | | bytes32 m3;
11101 | | bytes32 m4;
11102 | | bytes32 m5;
11103 | | bytes32 m6;
11104 | | /// @solidity memory-safe-assembly
11105 | | assembly {
11106 | | function writeString(pos, w) {
11107 | | let length := 0
11108 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11109 | | mstore(pos, length)
11110 | | let shift := sub(256, shl(3, length))
11111 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11112 | | }
11113 | | m0 := mload(0x00)
11114 | | m1 := mload(0x20)
11115 | | m2 := mload(0x40)
11116 | | m3 := mload(0x60)
11117 | | m4 := mload(0x80)
11118 | | m5 := mload(0xa0)
11119 | | m6 := mload(0xc0)
11120 | | // Selector of `log(string,address,uint256,address)`.
11121 | | mstore(0x00, 0x63fb8bc5)
11122 | | mstore(0x20, 0x80)
11123 | | mstore(0x40, p1)
11124 | | mstore(0x60, p2)
11125 | | mstore(0x80, p3)
11126 | | writeString(0xa0, p0)
11127 | | }
11128 | | _sendLogPayload(0x1c, 0xc4);
11129 | | /// @solidity memory-safe-assembly
11130 | | assembly {
11131 | | mstore(0x00, m0)
11132 | | mstore(0x20, m1)
11133 | | mstore(0x40, m2)
11134 | | mstore(0x60, m3)
11135 | | mstore(0x80, m4)
11136 | | mstore(0xa0, m5)
11137 | | mstore(0xc0, m6)
11138 | | }
11139 | | }
11140 | |
11141 | | function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure {
11142 | | bytes32 m0;
11143 | | bytes32 m1;
11144 | | bytes32 m2;
11145 | | bytes32 m3;
11146 | | bytes32 m4;
11147 | | bytes32 m5;
11148 | | bytes32 m6;
11149 | | /// @solidity memory-safe-assembly
11150 | | assembly {
11151 | | function writeString(pos, w) {
11152 | | let length := 0
11153 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11154 | | mstore(pos, length)
11155 | | let shift := sub(256, shl(3, length))
11156 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11157 | | }
11158 | | m0 := mload(0x00)
11159 | | m1 := mload(0x20)
11160 | | m2 := mload(0x40)
11161 | | m3 := mload(0x60)
11162 | | m4 := mload(0x80)
11163 | | m5 := mload(0xa0)
11164 | | m6 := mload(0xc0)
11165 | | // Selector of `log(string,address,uint256,bool)`.
11166 | | mstore(0x00, 0xfc4845f0)
11167 | | mstore(0x20, 0x80)
11168 | | mstore(0x40, p1)
11169 | | mstore(0x60, p2)
11170 | | mstore(0x80, p3)
11171 | | writeString(0xa0, p0)
11172 | | }
11173 | | _sendLogPayload(0x1c, 0xc4);
11174 | | /// @solidity memory-safe-assembly
11175 | | assembly {
11176 | | mstore(0x00, m0)
11177 | | mstore(0x20, m1)
11178 | | mstore(0x40, m2)
11179 | | mstore(0x60, m3)
11180 | | mstore(0x80, m4)
11181 | | mstore(0xa0, m5)
11182 | | mstore(0xc0, m6)
11183 | | }
11184 | | }
11185 | |
11186 | | function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure {
11187 | | bytes32 m0;
11188 | | bytes32 m1;
11189 | | bytes32 m2;
11190 | | bytes32 m3;
11191 | | bytes32 m4;
11192 | | bytes32 m5;
11193 | | bytes32 m6;
11194 | | /// @solidity memory-safe-assembly
11195 | | assembly {
11196 | | function writeString(pos, w) {
11197 | | let length := 0
11198 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11199 | | mstore(pos, length)
11200 | | let shift := sub(256, shl(3, length))
11201 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11202 | | }
11203 | | m0 := mload(0x00)
11204 | | m1 := mload(0x20)
11205 | | m2 := mload(0x40)
11206 | | m3 := mload(0x60)
11207 | | m4 := mload(0x80)
11208 | | m5 := mload(0xa0)
11209 | | m6 := mload(0xc0)
11210 | | // Selector of `log(string,address,uint256,uint256)`.
11211 | | mstore(0x00, 0xf8f51b1e)
11212 | | mstore(0x20, 0x80)
11213 | | mstore(0x40, p1)
11214 | | mstore(0x60, p2)
11215 | | mstore(0x80, p3)
11216 | | writeString(0xa0, p0)
11217 | | }
11218 | | _sendLogPayload(0x1c, 0xc4);
11219 | | /// @solidity memory-safe-assembly
11220 | | assembly {
11221 | | mstore(0x00, m0)
11222 | | mstore(0x20, m1)
11223 | | mstore(0x40, m2)
11224 | | mstore(0x60, m3)
11225 | | mstore(0x80, m4)
11226 | | mstore(0xa0, m5)
11227 | | mstore(0xc0, m6)
11228 | | }
11229 | | }
11230 | |
11231 | | function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure {
11232 | | bytes32 m0;
11233 | | bytes32 m1;
11234 | | bytes32 m2;
11235 | | bytes32 m3;
11236 | | bytes32 m4;
11237 | | bytes32 m5;
11238 | | bytes32 m6;
11239 | | bytes32 m7;
11240 | | bytes32 m8;
11241 | | /// @solidity memory-safe-assembly
11242 | | assembly {
11243 | | function writeString(pos, w) {
11244 | | let length := 0
11245 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11246 | | mstore(pos, length)
11247 | | let shift := sub(256, shl(3, length))
11248 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11249 | | }
11250 | | m0 := mload(0x00)
11251 | | m1 := mload(0x20)
11252 | | m2 := mload(0x40)
11253 | | m3 := mload(0x60)
11254 | | m4 := mload(0x80)
11255 | | m5 := mload(0xa0)
11256 | | m6 := mload(0xc0)
11257 | | m7 := mload(0xe0)
11258 | | m8 := mload(0x100)
11259 | | // Selector of `log(string,address,uint256,string)`.
11260 | | mstore(0x00, 0x5a477632)
11261 | | mstore(0x20, 0x80)
11262 | | mstore(0x40, p1)
11263 | | mstore(0x60, p2)
11264 | | mstore(0x80, 0xc0)
11265 | | writeString(0xa0, p0)
11266 | | writeString(0xe0, p3)
11267 | | }
11268 | | _sendLogPayload(0x1c, 0x104);
11269 | | /// @solidity memory-safe-assembly
11270 | | assembly {
11271 | | mstore(0x00, m0)
11272 | | mstore(0x20, m1)
11273 | | mstore(0x40, m2)
11274 | | mstore(0x60, m3)
11275 | | mstore(0x80, m4)
11276 | | mstore(0xa0, m5)
11277 | | mstore(0xc0, m6)
11278 | | mstore(0xe0, m7)
11279 | | mstore(0x100, m8)
11280 | | }
11281 | | }
11282 | |
11283 | | function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure {
11284 | | bytes32 m0;
11285 | | bytes32 m1;
11286 | | bytes32 m2;
11287 | | bytes32 m3;
11288 | | bytes32 m4;
11289 | | bytes32 m5;
11290 | | bytes32 m6;
11291 | | bytes32 m7;
11292 | | bytes32 m8;
11293 | | /// @solidity memory-safe-assembly
11294 | | assembly {
11295 | | function writeString(pos, w) {
11296 | | let length := 0
11297 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11298 | | mstore(pos, length)
11299 | | let shift := sub(256, shl(3, length))
11300 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11301 | | }
11302 | | m0 := mload(0x00)
11303 | | m1 := mload(0x20)
11304 | | m2 := mload(0x40)
11305 | | m3 := mload(0x60)
11306 | | m4 := mload(0x80)
11307 | | m5 := mload(0xa0)
11308 | | m6 := mload(0xc0)
11309 | | m7 := mload(0xe0)
11310 | | m8 := mload(0x100)
11311 | | // Selector of `log(string,address,string,address)`.
11312 | | mstore(0x00, 0xaabc9a31)
11313 | | mstore(0x20, 0x80)
11314 | | mstore(0x40, p1)
11315 | | mstore(0x60, 0xc0)
11316 | | mstore(0x80, p3)
11317 | | writeString(0xa0, p0)
11318 | | writeString(0xe0, p2)
11319 | | }
11320 | | _sendLogPayload(0x1c, 0x104);
11321 | | /// @solidity memory-safe-assembly
11322 | | assembly {
11323 | | mstore(0x00, m0)
11324 | | mstore(0x20, m1)
11325 | | mstore(0x40, m2)
11326 | | mstore(0x60, m3)
11327 | | mstore(0x80, m4)
11328 | | mstore(0xa0, m5)
11329 | | mstore(0xc0, m6)
11330 | | mstore(0xe0, m7)
11331 | | mstore(0x100, m8)
11332 | | }
11333 | | }
11334 | |
11335 | | function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure {
11336 | | bytes32 m0;
11337 | | bytes32 m1;
11338 | | bytes32 m2;
11339 | | bytes32 m3;
11340 | | bytes32 m4;
11341 | | bytes32 m5;
11342 | | bytes32 m6;
11343 | | bytes32 m7;
11344 | | bytes32 m8;
11345 | | /// @solidity memory-safe-assembly
11346 | | assembly {
11347 | | function writeString(pos, w) {
11348 | | let length := 0
11349 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11350 | | mstore(pos, length)
11351 | | let shift := sub(256, shl(3, length))
11352 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11353 | | }
11354 | | m0 := mload(0x00)
11355 | | m1 := mload(0x20)
11356 | | m2 := mload(0x40)
11357 | | m3 := mload(0x60)
11358 | | m4 := mload(0x80)
11359 | | m5 := mload(0xa0)
11360 | | m6 := mload(0xc0)
11361 | | m7 := mload(0xe0)
11362 | | m8 := mload(0x100)
11363 | | // Selector of `log(string,address,string,bool)`.
11364 | | mstore(0x00, 0x5f15d28c)
11365 | | mstore(0x20, 0x80)
11366 | | mstore(0x40, p1)
11367 | | mstore(0x60, 0xc0)
11368 | | mstore(0x80, p3)
11369 | | writeString(0xa0, p0)
11370 | | writeString(0xe0, p2)
11371 | | }
11372 | | _sendLogPayload(0x1c, 0x104);
11373 | | /// @solidity memory-safe-assembly
11374 | | assembly {
11375 | | mstore(0x00, m0)
11376 | | mstore(0x20, m1)
11377 | | mstore(0x40, m2)
11378 | | mstore(0x60, m3)
11379 | | mstore(0x80, m4)
11380 | | mstore(0xa0, m5)
11381 | | mstore(0xc0, m6)
11382 | | mstore(0xe0, m7)
11383 | | mstore(0x100, m8)
11384 | | }
11385 | | }
11386 | |
11387 | | function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure {
11388 | | bytes32 m0;
11389 | | bytes32 m1;
11390 | | bytes32 m2;
11391 | | bytes32 m3;
11392 | | bytes32 m4;
11393 | | bytes32 m5;
11394 | | bytes32 m6;
11395 | | bytes32 m7;
11396 | | bytes32 m8;
11397 | | /// @solidity memory-safe-assembly
11398 | | assembly {
11399 | | function writeString(pos, w) {
11400 | | let length := 0
11401 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11402 | | mstore(pos, length)
11403 | | let shift := sub(256, shl(3, length))
11404 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11405 | | }
11406 | | m0 := mload(0x00)
11407 | | m1 := mload(0x20)
11408 | | m2 := mload(0x40)
11409 | | m3 := mload(0x60)
11410 | | m4 := mload(0x80)
11411 | | m5 := mload(0xa0)
11412 | | m6 := mload(0xc0)
11413 | | m7 := mload(0xe0)
11414 | | m8 := mload(0x100)
11415 | | // Selector of `log(string,address,string,uint256)`.
11416 | | mstore(0x00, 0x91d1112e)
11417 | | mstore(0x20, 0x80)
11418 | | mstore(0x40, p1)
11419 | | mstore(0x60, 0xc0)
11420 | | mstore(0x80, p3)
11421 | | writeString(0xa0, p0)
11422 | | writeString(0xe0, p2)
11423 | | }
11424 | | _sendLogPayload(0x1c, 0x104);
11425 | | /// @solidity memory-safe-assembly
11426 | | assembly {
11427 | | mstore(0x00, m0)
11428 | | mstore(0x20, m1)
11429 | | mstore(0x40, m2)
11430 | | mstore(0x60, m3)
11431 | | mstore(0x80, m4)
11432 | | mstore(0xa0, m5)
11433 | | mstore(0xc0, m6)
11434 | | mstore(0xe0, m7)
11435 | | mstore(0x100, m8)
11436 | | }
11437 | | }
11438 | |
11439 | | function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
11440 | | bytes32 m0;
11441 | | bytes32 m1;
11442 | | bytes32 m2;
11443 | | bytes32 m3;
11444 | | bytes32 m4;
11445 | | bytes32 m5;
11446 | | bytes32 m6;
11447 | | bytes32 m7;
11448 | | bytes32 m8;
11449 | | bytes32 m9;
11450 | | bytes32 m10;
11451 | | /// @solidity memory-safe-assembly
11452 | | assembly {
11453 | | function writeString(pos, w) {
11454 | | let length := 0
11455 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11456 | | mstore(pos, length)
11457 | | let shift := sub(256, shl(3, length))
11458 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11459 | | }
11460 | | m0 := mload(0x00)
11461 | | m1 := mload(0x20)
11462 | | m2 := mload(0x40)
11463 | | m3 := mload(0x60)
11464 | | m4 := mload(0x80)
11465 | | m5 := mload(0xa0)
11466 | | m6 := mload(0xc0)
11467 | | m7 := mload(0xe0)
11468 | | m8 := mload(0x100)
11469 | | m9 := mload(0x120)
11470 | | m10 := mload(0x140)
11471 | | // Selector of `log(string,address,string,string)`.
11472 | | mstore(0x00, 0x245986f2)
11473 | | mstore(0x20, 0x80)
11474 | | mstore(0x40, p1)
11475 | | mstore(0x60, 0xc0)
11476 | | mstore(0x80, 0x100)
11477 | | writeString(0xa0, p0)
11478 | | writeString(0xe0, p2)
11479 | | writeString(0x120, p3)
11480 | | }
11481 | | _sendLogPayload(0x1c, 0x144);
11482 | | /// @solidity memory-safe-assembly
11483 | | assembly {
11484 | | mstore(0x00, m0)
11485 | | mstore(0x20, m1)
11486 | | mstore(0x40, m2)
11487 | | mstore(0x60, m3)
11488 | | mstore(0x80, m4)
11489 | | mstore(0xa0, m5)
11490 | | mstore(0xc0, m6)
11491 | | mstore(0xe0, m7)
11492 | | mstore(0x100, m8)
11493 | | mstore(0x120, m9)
11494 | | mstore(0x140, m10)
11495 | | }
11496 | | }
11497 | |
11498 | | function log(bytes32 p0, bool p1, address p2, address p3) internal pure {
11499 | | bytes32 m0;
11500 | | bytes32 m1;
11501 | | bytes32 m2;
11502 | | bytes32 m3;
11503 | | bytes32 m4;
11504 | | bytes32 m5;
11505 | | bytes32 m6;
11506 | | /// @solidity memory-safe-assembly
11507 | | assembly {
11508 | | function writeString(pos, w) {
11509 | | let length := 0
11510 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11511 | | mstore(pos, length)
11512 | | let shift := sub(256, shl(3, length))
11513 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11514 | | }
11515 | | m0 := mload(0x00)
11516 | | m1 := mload(0x20)
11517 | | m2 := mload(0x40)
11518 | | m3 := mload(0x60)
11519 | | m4 := mload(0x80)
11520 | | m5 := mload(0xa0)
11521 | | m6 := mload(0xc0)
11522 | | // Selector of `log(string,bool,address,address)`.
11523 | | mstore(0x00, 0x33e9dd1d)
11524 | | mstore(0x20, 0x80)
11525 | | mstore(0x40, p1)
11526 | | mstore(0x60, p2)
11527 | | mstore(0x80, p3)
11528 | | writeString(0xa0, p0)
11529 | | }
11530 | | _sendLogPayload(0x1c, 0xc4);
11531 | | /// @solidity memory-safe-assembly
11532 | | assembly {
11533 | | mstore(0x00, m0)
11534 | | mstore(0x20, m1)
11535 | | mstore(0x40, m2)
11536 | | mstore(0x60, m3)
11537 | | mstore(0x80, m4)
11538 | | mstore(0xa0, m5)
11539 | | mstore(0xc0, m6)
11540 | | }
11541 | | }
11542 | |
11543 | | function log(bytes32 p0, bool p1, address p2, bool p3) internal pure {
11544 | | bytes32 m0;
11545 | | bytes32 m1;
11546 | | bytes32 m2;
11547 | | bytes32 m3;
11548 | | bytes32 m4;
11549 | | bytes32 m5;
11550 | | bytes32 m6;
11551 | | /// @solidity memory-safe-assembly
11552 | | assembly {
11553 | | function writeString(pos, w) {
11554 | | let length := 0
11555 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11556 | | mstore(pos, length)
11557 | | let shift := sub(256, shl(3, length))
11558 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11559 | | }
11560 | | m0 := mload(0x00)
11561 | | m1 := mload(0x20)
11562 | | m2 := mload(0x40)
11563 | | m3 := mload(0x60)
11564 | | m4 := mload(0x80)
11565 | | m5 := mload(0xa0)
11566 | | m6 := mload(0xc0)
11567 | | // Selector of `log(string,bool,address,bool)`.
11568 | | mstore(0x00, 0x958c28c6)
11569 | | mstore(0x20, 0x80)
11570 | | mstore(0x40, p1)
11571 | | mstore(0x60, p2)
11572 | | mstore(0x80, p3)
11573 | | writeString(0xa0, p0)
11574 | | }
11575 | | _sendLogPayload(0x1c, 0xc4);
11576 | | /// @solidity memory-safe-assembly
11577 | | assembly {
11578 | | mstore(0x00, m0)
11579 | | mstore(0x20, m1)
11580 | | mstore(0x40, m2)
11581 | | mstore(0x60, m3)
11582 | | mstore(0x80, m4)
11583 | | mstore(0xa0, m5)
11584 | | mstore(0xc0, m6)
11585 | | }
11586 | | }
11587 | |
11588 | | function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure {
11589 | | bytes32 m0;
11590 | | bytes32 m1;
11591 | | bytes32 m2;
11592 | | bytes32 m3;
11593 | | bytes32 m4;
11594 | | bytes32 m5;
11595 | | bytes32 m6;
11596 | | /// @solidity memory-safe-assembly
11597 | | assembly {
11598 | | function writeString(pos, w) {
11599 | | let length := 0
11600 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11601 | | mstore(pos, length)
11602 | | let shift := sub(256, shl(3, length))
11603 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11604 | | }
11605 | | m0 := mload(0x00)
11606 | | m1 := mload(0x20)
11607 | | m2 := mload(0x40)
11608 | | m3 := mload(0x60)
11609 | | m4 := mload(0x80)
11610 | | m5 := mload(0xa0)
11611 | | m6 := mload(0xc0)
11612 | | // Selector of `log(string,bool,address,uint256)`.
11613 | | mstore(0x00, 0x5d08bb05)
11614 | | mstore(0x20, 0x80)
11615 | | mstore(0x40, p1)
11616 | | mstore(0x60, p2)
11617 | | mstore(0x80, p3)
11618 | | writeString(0xa0, p0)
11619 | | }
11620 | | _sendLogPayload(0x1c, 0xc4);
11621 | | /// @solidity memory-safe-assembly
11622 | | assembly {
11623 | | mstore(0x00, m0)
11624 | | mstore(0x20, m1)
11625 | | mstore(0x40, m2)
11626 | | mstore(0x60, m3)
11627 | | mstore(0x80, m4)
11628 | | mstore(0xa0, m5)
11629 | | mstore(0xc0, m6)
11630 | | }
11631 | | }
11632 | |
11633 | | function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure {
11634 | | bytes32 m0;
11635 | | bytes32 m1;
11636 | | bytes32 m2;
11637 | | bytes32 m3;
11638 | | bytes32 m4;
11639 | | bytes32 m5;
11640 | | bytes32 m6;
11641 | | bytes32 m7;
11642 | | bytes32 m8;
11643 | | /// @solidity memory-safe-assembly
11644 | | assembly {
11645 | | function writeString(pos, w) {
11646 | | let length := 0
11647 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11648 | | mstore(pos, length)
11649 | | let shift := sub(256, shl(3, length))
11650 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11651 | | }
11652 | | m0 := mload(0x00)
11653 | | m1 := mload(0x20)
11654 | | m2 := mload(0x40)
11655 | | m3 := mload(0x60)
11656 | | m4 := mload(0x80)
11657 | | m5 := mload(0xa0)
11658 | | m6 := mload(0xc0)
11659 | | m7 := mload(0xe0)
11660 | | m8 := mload(0x100)
11661 | | // Selector of `log(string,bool,address,string)`.
11662 | | mstore(0x00, 0x2d8e33a4)
11663 | | mstore(0x20, 0x80)
11664 | | mstore(0x40, p1)
11665 | | mstore(0x60, p2)
11666 | | mstore(0x80, 0xc0)
11667 | | writeString(0xa0, p0)
11668 | | writeString(0xe0, p3)
11669 | | }
11670 | | _sendLogPayload(0x1c, 0x104);
11671 | | /// @solidity memory-safe-assembly
11672 | | assembly {
11673 | | mstore(0x00, m0)
11674 | | mstore(0x20, m1)
11675 | | mstore(0x40, m2)
11676 | | mstore(0x60, m3)
11677 | | mstore(0x80, m4)
11678 | | mstore(0xa0, m5)
11679 | | mstore(0xc0, m6)
11680 | | mstore(0xe0, m7)
11681 | | mstore(0x100, m8)
11682 | | }
11683 | | }
11684 | |
11685 | | function log(bytes32 p0, bool p1, bool p2, address p3) internal pure {
11686 | | bytes32 m0;
11687 | | bytes32 m1;
11688 | | bytes32 m2;
11689 | | bytes32 m3;
11690 | | bytes32 m4;
11691 | | bytes32 m5;
11692 | | bytes32 m6;
11693 | | /// @solidity memory-safe-assembly
11694 | | assembly {
11695 | | function writeString(pos, w) {
11696 | | let length := 0
11697 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11698 | | mstore(pos, length)
11699 | | let shift := sub(256, shl(3, length))
11700 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11701 | | }
11702 | | m0 := mload(0x00)
11703 | | m1 := mload(0x20)
11704 | | m2 := mload(0x40)
11705 | | m3 := mload(0x60)
11706 | | m4 := mload(0x80)
11707 | | m5 := mload(0xa0)
11708 | | m6 := mload(0xc0)
11709 | | // Selector of `log(string,bool,bool,address)`.
11710 | | mstore(0x00, 0x7190a529)
11711 | | mstore(0x20, 0x80)
11712 | | mstore(0x40, p1)
11713 | | mstore(0x60, p2)
11714 | | mstore(0x80, p3)
11715 | | writeString(0xa0, p0)
11716 | | }
11717 | | _sendLogPayload(0x1c, 0xc4);
11718 | | /// @solidity memory-safe-assembly
11719 | | assembly {
11720 | | mstore(0x00, m0)
11721 | | mstore(0x20, m1)
11722 | | mstore(0x40, m2)
11723 | | mstore(0x60, m3)
11724 | | mstore(0x80, m4)
11725 | | mstore(0xa0, m5)
11726 | | mstore(0xc0, m6)
11727 | | }
11728 | | }
11729 | |
11730 | | function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure {
11731 | | bytes32 m0;
11732 | | bytes32 m1;
11733 | | bytes32 m2;
11734 | | bytes32 m3;
11735 | | bytes32 m4;
11736 | | bytes32 m5;
11737 | | bytes32 m6;
11738 | | /// @solidity memory-safe-assembly
11739 | | assembly {
11740 | | function writeString(pos, w) {
11741 | | let length := 0
11742 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11743 | | mstore(pos, length)
11744 | | let shift := sub(256, shl(3, length))
11745 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11746 | | }
11747 | | m0 := mload(0x00)
11748 | | m1 := mload(0x20)
11749 | | m2 := mload(0x40)
11750 | | m3 := mload(0x60)
11751 | | m4 := mload(0x80)
11752 | | m5 := mload(0xa0)
11753 | | m6 := mload(0xc0)
11754 | | // Selector of `log(string,bool,bool,bool)`.
11755 | | mstore(0x00, 0x895af8c5)
11756 | | mstore(0x20, 0x80)
11757 | | mstore(0x40, p1)
11758 | | mstore(0x60, p2)
11759 | | mstore(0x80, p3)
11760 | | writeString(0xa0, p0)
11761 | | }
11762 | | _sendLogPayload(0x1c, 0xc4);
11763 | | /// @solidity memory-safe-assembly
11764 | | assembly {
11765 | | mstore(0x00, m0)
11766 | | mstore(0x20, m1)
11767 | | mstore(0x40, m2)
11768 | | mstore(0x60, m3)
11769 | | mstore(0x80, m4)
11770 | | mstore(0xa0, m5)
11771 | | mstore(0xc0, m6)
11772 | | }
11773 | | }
11774 | |
11775 | | function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure {
11776 | | bytes32 m0;
11777 | | bytes32 m1;
11778 | | bytes32 m2;
11779 | | bytes32 m3;
11780 | | bytes32 m4;
11781 | | bytes32 m5;
11782 | | bytes32 m6;
11783 | | /// @solidity memory-safe-assembly
11784 | | assembly {
11785 | | function writeString(pos, w) {
11786 | | let length := 0
11787 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11788 | | mstore(pos, length)
11789 | | let shift := sub(256, shl(3, length))
11790 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11791 | | }
11792 | | m0 := mload(0x00)
11793 | | m1 := mload(0x20)
11794 | | m2 := mload(0x40)
11795 | | m3 := mload(0x60)
11796 | | m4 := mload(0x80)
11797 | | m5 := mload(0xa0)
11798 | | m6 := mload(0xc0)
11799 | | // Selector of `log(string,bool,bool,uint256)`.
11800 | | mstore(0x00, 0x8e3f78a9)
11801 | | mstore(0x20, 0x80)
11802 | | mstore(0x40, p1)
11803 | | mstore(0x60, p2)
11804 | | mstore(0x80, p3)
11805 | | writeString(0xa0, p0)
11806 | | }
11807 | | _sendLogPayload(0x1c, 0xc4);
11808 | | /// @solidity memory-safe-assembly
11809 | | assembly {
11810 | | mstore(0x00, m0)
11811 | | mstore(0x20, m1)
11812 | | mstore(0x40, m2)
11813 | | mstore(0x60, m3)
11814 | | mstore(0x80, m4)
11815 | | mstore(0xa0, m5)
11816 | | mstore(0xc0, m6)
11817 | | }
11818 | | }
11819 | |
11820 | | function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure {
11821 | | bytes32 m0;
11822 | | bytes32 m1;
11823 | | bytes32 m2;
11824 | | bytes32 m3;
11825 | | bytes32 m4;
11826 | | bytes32 m5;
11827 | | bytes32 m6;
11828 | | bytes32 m7;
11829 | | bytes32 m8;
11830 | | /// @solidity memory-safe-assembly
11831 | | assembly {
11832 | | function writeString(pos, w) {
11833 | | let length := 0
11834 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11835 | | mstore(pos, length)
11836 | | let shift := sub(256, shl(3, length))
11837 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11838 | | }
11839 | | m0 := mload(0x00)
11840 | | m1 := mload(0x20)
11841 | | m2 := mload(0x40)
11842 | | m3 := mload(0x60)
11843 | | m4 := mload(0x80)
11844 | | m5 := mload(0xa0)
11845 | | m6 := mload(0xc0)
11846 | | m7 := mload(0xe0)
11847 | | m8 := mload(0x100)
11848 | | // Selector of `log(string,bool,bool,string)`.
11849 | | mstore(0x00, 0x9d22d5dd)
11850 | | mstore(0x20, 0x80)
11851 | | mstore(0x40, p1)
11852 | | mstore(0x60, p2)
11853 | | mstore(0x80, 0xc0)
11854 | | writeString(0xa0, p0)
11855 | | writeString(0xe0, p3)
11856 | | }
11857 | | _sendLogPayload(0x1c, 0x104);
11858 | | /// @solidity memory-safe-assembly
11859 | | assembly {
11860 | | mstore(0x00, m0)
11861 | | mstore(0x20, m1)
11862 | | mstore(0x40, m2)
11863 | | mstore(0x60, m3)
11864 | | mstore(0x80, m4)
11865 | | mstore(0xa0, m5)
11866 | | mstore(0xc0, m6)
11867 | | mstore(0xe0, m7)
11868 | | mstore(0x100, m8)
11869 | | }
11870 | | }
11871 | |
11872 | | function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure {
11873 | | bytes32 m0;
11874 | | bytes32 m1;
11875 | | bytes32 m2;
11876 | | bytes32 m3;
11877 | | bytes32 m4;
11878 | | bytes32 m5;
11879 | | bytes32 m6;
11880 | | /// @solidity memory-safe-assembly
11881 | | assembly {
11882 | | function writeString(pos, w) {
11883 | | let length := 0
11884 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11885 | | mstore(pos, length)
11886 | | let shift := sub(256, shl(3, length))
11887 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11888 | | }
11889 | | m0 := mload(0x00)
11890 | | m1 := mload(0x20)
11891 | | m2 := mload(0x40)
11892 | | m3 := mload(0x60)
11893 | | m4 := mload(0x80)
11894 | | m5 := mload(0xa0)
11895 | | m6 := mload(0xc0)
11896 | | // Selector of `log(string,bool,uint256,address)`.
11897 | | mstore(0x00, 0x935e09bf)
11898 | | mstore(0x20, 0x80)
11899 | | mstore(0x40, p1)
11900 | | mstore(0x60, p2)
11901 | | mstore(0x80, p3)
11902 | | writeString(0xa0, p0)
11903 | | }
11904 | | _sendLogPayload(0x1c, 0xc4);
11905 | | /// @solidity memory-safe-assembly
11906 | | assembly {
11907 | | mstore(0x00, m0)
11908 | | mstore(0x20, m1)
11909 | | mstore(0x40, m2)
11910 | | mstore(0x60, m3)
11911 | | mstore(0x80, m4)
11912 | | mstore(0xa0, m5)
11913 | | mstore(0xc0, m6)
11914 | | }
11915 | | }
11916 | |
11917 | | function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure {
11918 | | bytes32 m0;
11919 | | bytes32 m1;
11920 | | bytes32 m2;
11921 | | bytes32 m3;
11922 | | bytes32 m4;
11923 | | bytes32 m5;
11924 | | bytes32 m6;
11925 | | /// @solidity memory-safe-assembly
11926 | | assembly {
11927 | | function writeString(pos, w) {
11928 | | let length := 0
11929 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11930 | | mstore(pos, length)
11931 | | let shift := sub(256, shl(3, length))
11932 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11933 | | }
11934 | | m0 := mload(0x00)
11935 | | m1 := mload(0x20)
11936 | | m2 := mload(0x40)
11937 | | m3 := mload(0x60)
11938 | | m4 := mload(0x80)
11939 | | m5 := mload(0xa0)
11940 | | m6 := mload(0xc0)
11941 | | // Selector of `log(string,bool,uint256,bool)`.
11942 | | mstore(0x00, 0x8af7cf8a)
11943 | | mstore(0x20, 0x80)
11944 | | mstore(0x40, p1)
11945 | | mstore(0x60, p2)
11946 | | mstore(0x80, p3)
11947 | | writeString(0xa0, p0)
11948 | | }
11949 | | _sendLogPayload(0x1c, 0xc4);
11950 | | /// @solidity memory-safe-assembly
11951 | | assembly {
11952 | | mstore(0x00, m0)
11953 | | mstore(0x20, m1)
11954 | | mstore(0x40, m2)
11955 | | mstore(0x60, m3)
11956 | | mstore(0x80, m4)
11957 | | mstore(0xa0, m5)
11958 | | mstore(0xc0, m6)
11959 | | }
11960 | | }
11961 | |
11962 | | function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure {
11963 | | bytes32 m0;
11964 | | bytes32 m1;
11965 | | bytes32 m2;
11966 | | bytes32 m3;
11967 | | bytes32 m4;
11968 | | bytes32 m5;
11969 | | bytes32 m6;
11970 | | /// @solidity memory-safe-assembly
11971 | | assembly {
11972 | | function writeString(pos, w) {
11973 | | let length := 0
11974 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11975 | | mstore(pos, length)
11976 | | let shift := sub(256, shl(3, length))
11977 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11978 | | }
11979 | | m0 := mload(0x00)
11980 | | m1 := mload(0x20)
11981 | | m2 := mload(0x40)
11982 | | m3 := mload(0x60)
11983 | | m4 := mload(0x80)
11984 | | m5 := mload(0xa0)
11985 | | m6 := mload(0xc0)
11986 | | // Selector of `log(string,bool,uint256,uint256)`.
11987 | | mstore(0x00, 0x64b5bb67)
11988 | | mstore(0x20, 0x80)
11989 | | mstore(0x40, p1)
11990 | | mstore(0x60, p2)
11991 | | mstore(0x80, p3)
11992 | | writeString(0xa0, p0)
11993 | | }
11994 | | _sendLogPayload(0x1c, 0xc4);
11995 | | /// @solidity memory-safe-assembly
11996 | | assembly {
11997 | | mstore(0x00, m0)
11998 | | mstore(0x20, m1)
11999 | | mstore(0x40, m2)
12000 | | mstore(0x60, m3)
12001 | | mstore(0x80, m4)
12002 | | mstore(0xa0, m5)
12003 | | mstore(0xc0, m6)
12004 | | }
12005 | | }
12006 | |
12007 | | function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
12008 | | bytes32 m0;
12009 | | bytes32 m1;
12010 | | bytes32 m2;
12011 | | bytes32 m3;
12012 | | bytes32 m4;
12013 | | bytes32 m5;
12014 | | bytes32 m6;
12015 | | bytes32 m7;
12016 | | bytes32 m8;
12017 | | /// @solidity memory-safe-assembly
12018 | | assembly {
12019 | | function writeString(pos, w) {
12020 | | let length := 0
12021 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12022 | | mstore(pos, length)
12023 | | let shift := sub(256, shl(3, length))
12024 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12025 | | }
12026 | | m0 := mload(0x00)
12027 | | m1 := mload(0x20)
12028 | | m2 := mload(0x40)
12029 | | m3 := mload(0x60)
12030 | | m4 := mload(0x80)
12031 | | m5 := mload(0xa0)
12032 | | m6 := mload(0xc0)
12033 | | m7 := mload(0xe0)
12034 | | m8 := mload(0x100)
12035 | | // Selector of `log(string,bool,uint256,string)`.
12036 | | mstore(0x00, 0x742d6ee7)
12037 | | mstore(0x20, 0x80)
12038 | | mstore(0x40, p1)
12039 | | mstore(0x60, p2)
12040 | | mstore(0x80, 0xc0)
12041 | | writeString(0xa0, p0)
12042 | | writeString(0xe0, p3)
12043 | | }
12044 | | _sendLogPayload(0x1c, 0x104);
12045 | | /// @solidity memory-safe-assembly
12046 | | assembly {
12047 | | mstore(0x00, m0)
12048 | | mstore(0x20, m1)
12049 | | mstore(0x40, m2)
12050 | | mstore(0x60, m3)
12051 | | mstore(0x80, m4)
12052 | | mstore(0xa0, m5)
12053 | | mstore(0xc0, m6)
12054 | | mstore(0xe0, m7)
12055 | | mstore(0x100, m8)
12056 | | }
12057 | | }
12058 | |
12059 | | function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure {
12060 | | bytes32 m0;
12061 | | bytes32 m1;
12062 | | bytes32 m2;
12063 | | bytes32 m3;
12064 | | bytes32 m4;
12065 | | bytes32 m5;
12066 | | bytes32 m6;
12067 | | bytes32 m7;
12068 | | bytes32 m8;
12069 | | /// @solidity memory-safe-assembly
12070 | | assembly {
12071 | | function writeString(pos, w) {
12072 | | let length := 0
12073 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12074 | | mstore(pos, length)
12075 | | let shift := sub(256, shl(3, length))
12076 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12077 | | }
12078 | | m0 := mload(0x00)
12079 | | m1 := mload(0x20)
12080 | | m2 := mload(0x40)
12081 | | m3 := mload(0x60)
12082 | | m4 := mload(0x80)
12083 | | m5 := mload(0xa0)
12084 | | m6 := mload(0xc0)
12085 | | m7 := mload(0xe0)
12086 | | m8 := mload(0x100)
12087 | | // Selector of `log(string,bool,string,address)`.
12088 | | mstore(0x00, 0xe0625b29)
12089 | | mstore(0x20, 0x80)
12090 | | mstore(0x40, p1)
12091 | | mstore(0x60, 0xc0)
12092 | | mstore(0x80, p3)
12093 | | writeString(0xa0, p0)
12094 | | writeString(0xe0, p2)
12095 | | }
12096 | | _sendLogPayload(0x1c, 0x104);
12097 | | /// @solidity memory-safe-assembly
12098 | | assembly {
12099 | | mstore(0x00, m0)
12100 | | mstore(0x20, m1)
12101 | | mstore(0x40, m2)
12102 | | mstore(0x60, m3)
12103 | | mstore(0x80, m4)
12104 | | mstore(0xa0, m5)
12105 | | mstore(0xc0, m6)
12106 | | mstore(0xe0, m7)
12107 | | mstore(0x100, m8)
12108 | | }
12109 | | }
12110 | |
12111 | | function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure {
12112 | | bytes32 m0;
12113 | | bytes32 m1;
12114 | | bytes32 m2;
12115 | | bytes32 m3;
12116 | | bytes32 m4;
12117 | | bytes32 m5;
12118 | | bytes32 m6;
12119 | | bytes32 m7;
12120 | | bytes32 m8;
12121 | | /// @solidity memory-safe-assembly
12122 | | assembly {
12123 | | function writeString(pos, w) {
12124 | | let length := 0
12125 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12126 | | mstore(pos, length)
12127 | | let shift := sub(256, shl(3, length))
12128 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12129 | | }
12130 | | m0 := mload(0x00)
12131 | | m1 := mload(0x20)
12132 | | m2 := mload(0x40)
12133 | | m3 := mload(0x60)
12134 | | m4 := mload(0x80)
12135 | | m5 := mload(0xa0)
12136 | | m6 := mload(0xc0)
12137 | | m7 := mload(0xe0)
12138 | | m8 := mload(0x100)
12139 | | // Selector of `log(string,bool,string,bool)`.
12140 | | mstore(0x00, 0x3f8a701d)
12141 | | mstore(0x20, 0x80)
12142 | | mstore(0x40, p1)
12143 | | mstore(0x60, 0xc0)
12144 | | mstore(0x80, p3)
12145 | | writeString(0xa0, p0)
12146 | | writeString(0xe0, p2)
12147 | | }
12148 | | _sendLogPayload(0x1c, 0x104);
12149 | | /// @solidity memory-safe-assembly
12150 | | assembly {
12151 | | mstore(0x00, m0)
12152 | | mstore(0x20, m1)
12153 | | mstore(0x40, m2)
12154 | | mstore(0x60, m3)
12155 | | mstore(0x80, m4)
12156 | | mstore(0xa0, m5)
12157 | | mstore(0xc0, m6)
12158 | | mstore(0xe0, m7)
12159 | | mstore(0x100, m8)
12160 | | }
12161 | | }
12162 | |
12163 | | function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
12164 | | bytes32 m0;
12165 | | bytes32 m1;
12166 | | bytes32 m2;
12167 | | bytes32 m3;
12168 | | bytes32 m4;
12169 | | bytes32 m5;
12170 | | bytes32 m6;
12171 | | bytes32 m7;
12172 | | bytes32 m8;
12173 | | /// @solidity memory-safe-assembly
12174 | | assembly {
12175 | | function writeString(pos, w) {
12176 | | let length := 0
12177 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12178 | | mstore(pos, length)
12179 | | let shift := sub(256, shl(3, length))
12180 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12181 | | }
12182 | | m0 := mload(0x00)
12183 | | m1 := mload(0x20)
12184 | | m2 := mload(0x40)
12185 | | m3 := mload(0x60)
12186 | | m4 := mload(0x80)
12187 | | m5 := mload(0xa0)
12188 | | m6 := mload(0xc0)
12189 | | m7 := mload(0xe0)
12190 | | m8 := mload(0x100)
12191 | | // Selector of `log(string,bool,string,uint256)`.
12192 | | mstore(0x00, 0x24f91465)
12193 | | mstore(0x20, 0x80)
12194 | | mstore(0x40, p1)
12195 | | mstore(0x60, 0xc0)
12196 | | mstore(0x80, p3)
12197 | | writeString(0xa0, p0)
12198 | | writeString(0xe0, p2)
12199 | | }
12200 | | _sendLogPayload(0x1c, 0x104);
12201 | | /// @solidity memory-safe-assembly
12202 | | assembly {
12203 | | mstore(0x00, m0)
12204 | | mstore(0x20, m1)
12205 | | mstore(0x40, m2)
12206 | | mstore(0x60, m3)
12207 | | mstore(0x80, m4)
12208 | | mstore(0xa0, m5)
12209 | | mstore(0xc0, m6)
12210 | | mstore(0xe0, m7)
12211 | | mstore(0x100, m8)
12212 | | }
12213 | | }
12214 | |
12215 | | function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
12216 | | bytes32 m0;
12217 | | bytes32 m1;
12218 | | bytes32 m2;
12219 | | bytes32 m3;
12220 | | bytes32 m4;
12221 | | bytes32 m5;
12222 | | bytes32 m6;
12223 | | bytes32 m7;
12224 | | bytes32 m8;
12225 | | bytes32 m9;
12226 | | bytes32 m10;
12227 | | /// @solidity memory-safe-assembly
12228 | | assembly {
12229 | | function writeString(pos, w) {
12230 | | let length := 0
12231 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12232 | | mstore(pos, length)
12233 | | let shift := sub(256, shl(3, length))
12234 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12235 | | }
12236 | | m0 := mload(0x00)
12237 | | m1 := mload(0x20)
12238 | | m2 := mload(0x40)
12239 | | m3 := mload(0x60)
12240 | | m4 := mload(0x80)
12241 | | m5 := mload(0xa0)
12242 | | m6 := mload(0xc0)
12243 | | m7 := mload(0xe0)
12244 | | m8 := mload(0x100)
12245 | | m9 := mload(0x120)
12246 | | m10 := mload(0x140)
12247 | | // Selector of `log(string,bool,string,string)`.
12248 | | mstore(0x00, 0xa826caeb)
12249 | | mstore(0x20, 0x80)
12250 | | mstore(0x40, p1)
12251 | | mstore(0x60, 0xc0)
12252 | | mstore(0x80, 0x100)
12253 | | writeString(0xa0, p0)
12254 | | writeString(0xe0, p2)
12255 | | writeString(0x120, p3)
12256 | | }
12257 | | _sendLogPayload(0x1c, 0x144);
12258 | | /// @solidity memory-safe-assembly
12259 | | assembly {
12260 | | mstore(0x00, m0)
12261 | | mstore(0x20, m1)
12262 | | mstore(0x40, m2)
12263 | | mstore(0x60, m3)
12264 | | mstore(0x80, m4)
12265 | | mstore(0xa0, m5)
12266 | | mstore(0xc0, m6)
12267 | | mstore(0xe0, m7)
12268 | | mstore(0x100, m8)
12269 | | mstore(0x120, m9)
12270 | | mstore(0x140, m10)
12271 | | }
12272 | | }
12273 | |
12274 | | function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure {
12275 | | bytes32 m0;
12276 | | bytes32 m1;
12277 | | bytes32 m2;
12278 | | bytes32 m3;
12279 | | bytes32 m4;
12280 | | bytes32 m5;
12281 | | bytes32 m6;
12282 | | /// @solidity memory-safe-assembly
12283 | | assembly {
12284 | | function writeString(pos, w) {
12285 | | let length := 0
12286 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12287 | | mstore(pos, length)
12288 | | let shift := sub(256, shl(3, length))
12289 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12290 | | }
12291 | | m0 := mload(0x00)
12292 | | m1 := mload(0x20)
12293 | | m2 := mload(0x40)
12294 | | m3 := mload(0x60)
12295 | | m4 := mload(0x80)
12296 | | m5 := mload(0xa0)
12297 | | m6 := mload(0xc0)
12298 | | // Selector of `log(string,uint256,address,address)`.
12299 | | mstore(0x00, 0x5ea2b7ae)
12300 | | mstore(0x20, 0x80)
12301 | | mstore(0x40, p1)
12302 | | mstore(0x60, p2)
12303 | | mstore(0x80, p3)
12304 | | writeString(0xa0, p0)
12305 | | }
12306 | | _sendLogPayload(0x1c, 0xc4);
12307 | | /// @solidity memory-safe-assembly
12308 | | assembly {
12309 | | mstore(0x00, m0)
12310 | | mstore(0x20, m1)
12311 | | mstore(0x40, m2)
12312 | | mstore(0x60, m3)
12313 | | mstore(0x80, m4)
12314 | | mstore(0xa0, m5)
12315 | | mstore(0xc0, m6)
12316 | | }
12317 | | }
12318 | |
12319 | | function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure {
12320 | | bytes32 m0;
12321 | | bytes32 m1;
12322 | | bytes32 m2;
12323 | | bytes32 m3;
12324 | | bytes32 m4;
12325 | | bytes32 m5;
12326 | | bytes32 m6;
12327 | | /// @solidity memory-safe-assembly
12328 | | assembly {
12329 | | function writeString(pos, w) {
12330 | | let length := 0
12331 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12332 | | mstore(pos, length)
12333 | | let shift := sub(256, shl(3, length))
12334 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12335 | | }
12336 | | m0 := mload(0x00)
12337 | | m1 := mload(0x20)
12338 | | m2 := mload(0x40)
12339 | | m3 := mload(0x60)
12340 | | m4 := mload(0x80)
12341 | | m5 := mload(0xa0)
12342 | | m6 := mload(0xc0)
12343 | | // Selector of `log(string,uint256,address,bool)`.
12344 | | mstore(0x00, 0x82112a42)
12345 | | mstore(0x20, 0x80)
12346 | | mstore(0x40, p1)
12347 | | mstore(0x60, p2)
12348 | | mstore(0x80, p3)
12349 | | writeString(0xa0, p0)
12350 | | }
12351 | | _sendLogPayload(0x1c, 0xc4);
12352 | | /// @solidity memory-safe-assembly
12353 | | assembly {
12354 | | mstore(0x00, m0)
12355 | | mstore(0x20, m1)
12356 | | mstore(0x40, m2)
12357 | | mstore(0x60, m3)
12358 | | mstore(0x80, m4)
12359 | | mstore(0xa0, m5)
12360 | | mstore(0xc0, m6)
12361 | | }
12362 | | }
12363 | |
12364 | | function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure {
12365 | | bytes32 m0;
12366 | | bytes32 m1;
12367 | | bytes32 m2;
12368 | | bytes32 m3;
12369 | | bytes32 m4;
12370 | | bytes32 m5;
12371 | | bytes32 m6;
12372 | | /// @solidity memory-safe-assembly
12373 | | assembly {
12374 | | function writeString(pos, w) {
12375 | | let length := 0
12376 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12377 | | mstore(pos, length)
12378 | | let shift := sub(256, shl(3, length))
12379 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12380 | | }
12381 | | m0 := mload(0x00)
12382 | | m1 := mload(0x20)
12383 | | m2 := mload(0x40)
12384 | | m3 := mload(0x60)
12385 | | m4 := mload(0x80)
12386 | | m5 := mload(0xa0)
12387 | | m6 := mload(0xc0)
12388 | | // Selector of `log(string,uint256,address,uint256)`.
12389 | | mstore(0x00, 0x4f04fdc6)
12390 | | mstore(0x20, 0x80)
12391 | | mstore(0x40, p1)
12392 | | mstore(0x60, p2)
12393 | | mstore(0x80, p3)
12394 | | writeString(0xa0, p0)
12395 | | }
12396 | | _sendLogPayload(0x1c, 0xc4);
12397 | | /// @solidity memory-safe-assembly
12398 | | assembly {
12399 | | mstore(0x00, m0)
12400 | | mstore(0x20, m1)
12401 | | mstore(0x40, m2)
12402 | | mstore(0x60, m3)
12403 | | mstore(0x80, m4)
12404 | | mstore(0xa0, m5)
12405 | | mstore(0xc0, m6)
12406 | | }
12407 | | }
12408 | |
12409 | | function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure {
12410 | | bytes32 m0;
12411 | | bytes32 m1;
12412 | | bytes32 m2;
12413 | | bytes32 m3;
12414 | | bytes32 m4;
12415 | | bytes32 m5;
12416 | | bytes32 m6;
12417 | | bytes32 m7;
12418 | | bytes32 m8;
12419 | | /// @solidity memory-safe-assembly
12420 | | assembly {
12421 | | function writeString(pos, w) {
12422 | | let length := 0
12423 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12424 | | mstore(pos, length)
12425 | | let shift := sub(256, shl(3, length))
12426 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12427 | | }
12428 | | m0 := mload(0x00)
12429 | | m1 := mload(0x20)
12430 | | m2 := mload(0x40)
12431 | | m3 := mload(0x60)
12432 | | m4 := mload(0x80)
12433 | | m5 := mload(0xa0)
12434 | | m6 := mload(0xc0)
12435 | | m7 := mload(0xe0)
12436 | | m8 := mload(0x100)
12437 | | // Selector of `log(string,uint256,address,string)`.
12438 | | mstore(0x00, 0x9ffb2f93)
12439 | | mstore(0x20, 0x80)
12440 | | mstore(0x40, p1)
12441 | | mstore(0x60, p2)
12442 | | mstore(0x80, 0xc0)
12443 | | writeString(0xa0, p0)
12444 | | writeString(0xe0, p3)
12445 | | }
12446 | | _sendLogPayload(0x1c, 0x104);
12447 | | /// @solidity memory-safe-assembly
12448 | | assembly {
12449 | | mstore(0x00, m0)
12450 | | mstore(0x20, m1)
12451 | | mstore(0x40, m2)
12452 | | mstore(0x60, m3)
12453 | | mstore(0x80, m4)
12454 | | mstore(0xa0, m5)
12455 | | mstore(0xc0, m6)
12456 | | mstore(0xe0, m7)
12457 | | mstore(0x100, m8)
12458 | | }
12459 | | }
12460 | |
12461 | | function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure {
12462 | | bytes32 m0;
12463 | | bytes32 m1;
12464 | | bytes32 m2;
12465 | | bytes32 m3;
12466 | | bytes32 m4;
12467 | | bytes32 m5;
12468 | | bytes32 m6;
12469 | | /// @solidity memory-safe-assembly
12470 | | assembly {
12471 | | function writeString(pos, w) {
12472 | | let length := 0
12473 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12474 | | mstore(pos, length)
12475 | | let shift := sub(256, shl(3, length))
12476 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12477 | | }
12478 | | m0 := mload(0x00)
12479 | | m1 := mload(0x20)
12480 | | m2 := mload(0x40)
12481 | | m3 := mload(0x60)
12482 | | m4 := mload(0x80)
12483 | | m5 := mload(0xa0)
12484 | | m6 := mload(0xc0)
12485 | | // Selector of `log(string,uint256,bool,address)`.
12486 | | mstore(0x00, 0xe0e95b98)
12487 | | mstore(0x20, 0x80)
12488 | | mstore(0x40, p1)
12489 | | mstore(0x60, p2)
12490 | | mstore(0x80, p3)
12491 | | writeString(0xa0, p0)
12492 | | }
12493 | | _sendLogPayload(0x1c, 0xc4);
12494 | | /// @solidity memory-safe-assembly
12495 | | assembly {
12496 | | mstore(0x00, m0)
12497 | | mstore(0x20, m1)
12498 | | mstore(0x40, m2)
12499 | | mstore(0x60, m3)
12500 | | mstore(0x80, m4)
12501 | | mstore(0xa0, m5)
12502 | | mstore(0xc0, m6)
12503 | | }
12504 | | }
12505 | |
12506 | | function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure {
12507 | | bytes32 m0;
12508 | | bytes32 m1;
12509 | | bytes32 m2;
12510 | | bytes32 m3;
12511 | | bytes32 m4;
12512 | | bytes32 m5;
12513 | | bytes32 m6;
12514 | | /// @solidity memory-safe-assembly
12515 | | assembly {
12516 | | function writeString(pos, w) {
12517 | | let length := 0
12518 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12519 | | mstore(pos, length)
12520 | | let shift := sub(256, shl(3, length))
12521 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12522 | | }
12523 | | m0 := mload(0x00)
12524 | | m1 := mload(0x20)
12525 | | m2 := mload(0x40)
12526 | | m3 := mload(0x60)
12527 | | m4 := mload(0x80)
12528 | | m5 := mload(0xa0)
12529 | | m6 := mload(0xc0)
12530 | | // Selector of `log(string,uint256,bool,bool)`.
12531 | | mstore(0x00, 0x354c36d6)
12532 | | mstore(0x20, 0x80)
12533 | | mstore(0x40, p1)
12534 | | mstore(0x60, p2)
12535 | | mstore(0x80, p3)
12536 | | writeString(0xa0, p0)
12537 | | }
12538 | | _sendLogPayload(0x1c, 0xc4);
12539 | | /// @solidity memory-safe-assembly
12540 | | assembly {
12541 | | mstore(0x00, m0)
12542 | | mstore(0x20, m1)
12543 | | mstore(0x40, m2)
12544 | | mstore(0x60, m3)
12545 | | mstore(0x80, m4)
12546 | | mstore(0xa0, m5)
12547 | | mstore(0xc0, m6)
12548 | | }
12549 | | }
12550 | |
12551 | | function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure {
12552 | | bytes32 m0;
12553 | | bytes32 m1;
12554 | | bytes32 m2;
12555 | | bytes32 m3;
12556 | | bytes32 m4;
12557 | | bytes32 m5;
12558 | | bytes32 m6;
12559 | | /// @solidity memory-safe-assembly
12560 | | assembly {
12561 | | function writeString(pos, w) {
12562 | | let length := 0
12563 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12564 | | mstore(pos, length)
12565 | | let shift := sub(256, shl(3, length))
12566 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12567 | | }
12568 | | m0 := mload(0x00)
12569 | | m1 := mload(0x20)
12570 | | m2 := mload(0x40)
12571 | | m3 := mload(0x60)
12572 | | m4 := mload(0x80)
12573 | | m5 := mload(0xa0)
12574 | | m6 := mload(0xc0)
12575 | | // Selector of `log(string,uint256,bool,uint256)`.
12576 | | mstore(0x00, 0xe41b6f6f)
12577 | | mstore(0x20, 0x80)
12578 | | mstore(0x40, p1)
12579 | | mstore(0x60, p2)
12580 | | mstore(0x80, p3)
12581 | | writeString(0xa0, p0)
12582 | | }
12583 | | _sendLogPayload(0x1c, 0xc4);
12584 | | /// @solidity memory-safe-assembly
12585 | | assembly {
12586 | | mstore(0x00, m0)
12587 | | mstore(0x20, m1)
12588 | | mstore(0x40, m2)
12589 | | mstore(0x60, m3)
12590 | | mstore(0x80, m4)
12591 | | mstore(0xa0, m5)
12592 | | mstore(0xc0, m6)
12593 | | }
12594 | | }
12595 | |
12596 | | function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
12597 | | bytes32 m0;
12598 | | bytes32 m1;
12599 | | bytes32 m2;
12600 | | bytes32 m3;
12601 | | bytes32 m4;
12602 | | bytes32 m5;
12603 | | bytes32 m6;
12604 | | bytes32 m7;
12605 | | bytes32 m8;
12606 | | /// @solidity memory-safe-assembly
12607 | | assembly {
12608 | | function writeString(pos, w) {
12609 | | let length := 0
12610 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12611 | | mstore(pos, length)
12612 | | let shift := sub(256, shl(3, length))
12613 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12614 | | }
12615 | | m0 := mload(0x00)
12616 | | m1 := mload(0x20)
12617 | | m2 := mload(0x40)
12618 | | m3 := mload(0x60)
12619 | | m4 := mload(0x80)
12620 | | m5 := mload(0xa0)
12621 | | m6 := mload(0xc0)
12622 | | m7 := mload(0xe0)
12623 | | m8 := mload(0x100)
12624 | | // Selector of `log(string,uint256,bool,string)`.
12625 | | mstore(0x00, 0xabf73a98)
12626 | | mstore(0x20, 0x80)
12627 | | mstore(0x40, p1)
12628 | | mstore(0x60, p2)
12629 | | mstore(0x80, 0xc0)
12630 | | writeString(0xa0, p0)
12631 | | writeString(0xe0, p3)
12632 | | }
12633 | | _sendLogPayload(0x1c, 0x104);
12634 | | /// @solidity memory-safe-assembly
12635 | | assembly {
12636 | | mstore(0x00, m0)
12637 | | mstore(0x20, m1)
12638 | | mstore(0x40, m2)
12639 | | mstore(0x60, m3)
12640 | | mstore(0x80, m4)
12641 | | mstore(0xa0, m5)
12642 | | mstore(0xc0, m6)
12643 | | mstore(0xe0, m7)
12644 | | mstore(0x100, m8)
12645 | | }
12646 | | }
12647 | |
12648 | | function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure {
12649 | | bytes32 m0;
12650 | | bytes32 m1;
12651 | | bytes32 m2;
12652 | | bytes32 m3;
12653 | | bytes32 m4;
12654 | | bytes32 m5;
12655 | | bytes32 m6;
12656 | | /// @solidity memory-safe-assembly
12657 | | assembly {
12658 | | function writeString(pos, w) {
12659 | | let length := 0
12660 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12661 | | mstore(pos, length)
12662 | | let shift := sub(256, shl(3, length))
12663 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12664 | | }
12665 | | m0 := mload(0x00)
12666 | | m1 := mload(0x20)
12667 | | m2 := mload(0x40)
12668 | | m3 := mload(0x60)
12669 | | m4 := mload(0x80)
12670 | | m5 := mload(0xa0)
12671 | | m6 := mload(0xc0)
12672 | | // Selector of `log(string,uint256,uint256,address)`.
12673 | | mstore(0x00, 0xe21de278)
12674 | | mstore(0x20, 0x80)
12675 | | mstore(0x40, p1)
12676 | | mstore(0x60, p2)
12677 | | mstore(0x80, p3)
12678 | | writeString(0xa0, p0)
12679 | | }
12680 | | _sendLogPayload(0x1c, 0xc4);
12681 | | /// @solidity memory-safe-assembly
12682 | | assembly {
12683 | | mstore(0x00, m0)
12684 | | mstore(0x20, m1)
12685 | | mstore(0x40, m2)
12686 | | mstore(0x60, m3)
12687 | | mstore(0x80, m4)
12688 | | mstore(0xa0, m5)
12689 | | mstore(0xc0, m6)
12690 | | }
12691 | | }
12692 | |
12693 | | function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure {
12694 | | bytes32 m0;
12695 | | bytes32 m1;
12696 | | bytes32 m2;
12697 | | bytes32 m3;
12698 | | bytes32 m4;
12699 | | bytes32 m5;
12700 | | bytes32 m6;
12701 | | /// @solidity memory-safe-assembly
12702 | | assembly {
12703 | | function writeString(pos, w) {
12704 | | let length := 0
12705 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12706 | | mstore(pos, length)
12707 | | let shift := sub(256, shl(3, length))
12708 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12709 | | }
12710 | | m0 := mload(0x00)
12711 | | m1 := mload(0x20)
12712 | | m2 := mload(0x40)
12713 | | m3 := mload(0x60)
12714 | | m4 := mload(0x80)
12715 | | m5 := mload(0xa0)
12716 | | m6 := mload(0xc0)
12717 | | // Selector of `log(string,uint256,uint256,bool)`.
12718 | | mstore(0x00, 0x7626db92)
12719 | | mstore(0x20, 0x80)
12720 | | mstore(0x40, p1)
12721 | | mstore(0x60, p2)
12722 | | mstore(0x80, p3)
12723 | | writeString(0xa0, p0)
12724 | | }
12725 | | _sendLogPayload(0x1c, 0xc4);
12726 | | /// @solidity memory-safe-assembly
12727 | | assembly {
12728 | | mstore(0x00, m0)
12729 | | mstore(0x20, m1)
12730 | | mstore(0x40, m2)
12731 | | mstore(0x60, m3)
12732 | | mstore(0x80, m4)
12733 | | mstore(0xa0, m5)
12734 | | mstore(0xc0, m6)
12735 | | }
12736 | | }
12737 | |
12738 | | function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
12739 | | bytes32 m0;
12740 | | bytes32 m1;
12741 | | bytes32 m2;
12742 | | bytes32 m3;
12743 | | bytes32 m4;
12744 | | bytes32 m5;
12745 | | bytes32 m6;
12746 | | /// @solidity memory-safe-assembly
12747 | | assembly {
12748 | | function writeString(pos, w) {
12749 | | let length := 0
12750 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12751 | | mstore(pos, length)
12752 | | let shift := sub(256, shl(3, length))
12753 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12754 | | }
12755 | | m0 := mload(0x00)
12756 | | m1 := mload(0x20)
12757 | | m2 := mload(0x40)
12758 | | m3 := mload(0x60)
12759 | | m4 := mload(0x80)
12760 | | m5 := mload(0xa0)
12761 | | m6 := mload(0xc0)
12762 | | // Selector of `log(string,uint256,uint256,uint256)`.
12763 | | mstore(0x00, 0xa7a87853)
12764 | | mstore(0x20, 0x80)
12765 | | mstore(0x40, p1)
12766 | | mstore(0x60, p2)
12767 | | mstore(0x80, p3)
12768 | | writeString(0xa0, p0)
12769 | | }
12770 | | _sendLogPayload(0x1c, 0xc4);
12771 | | /// @solidity memory-safe-assembly
12772 | | assembly {
12773 | | mstore(0x00, m0)
12774 | | mstore(0x20, m1)
12775 | | mstore(0x40, m2)
12776 | | mstore(0x60, m3)
12777 | | mstore(0x80, m4)
12778 | | mstore(0xa0, m5)
12779 | | mstore(0xc0, m6)
12780 | | }
12781 | | }
12782 | |
12783 | | function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
12784 | | bytes32 m0;
12785 | | bytes32 m1;
12786 | | bytes32 m2;
12787 | | bytes32 m3;
12788 | | bytes32 m4;
12789 | | bytes32 m5;
12790 | | bytes32 m6;
12791 | | bytes32 m7;
12792 | | bytes32 m8;
12793 | | /// @solidity memory-safe-assembly
12794 | | assembly {
12795 | | function writeString(pos, w) {
12796 | | let length := 0
12797 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12798 | | mstore(pos, length)
12799 | | let shift := sub(256, shl(3, length))
12800 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12801 | | }
12802 | | m0 := mload(0x00)
12803 | | m1 := mload(0x20)
12804 | | m2 := mload(0x40)
12805 | | m3 := mload(0x60)
12806 | | m4 := mload(0x80)
12807 | | m5 := mload(0xa0)
12808 | | m6 := mload(0xc0)
12809 | | m7 := mload(0xe0)
12810 | | m8 := mload(0x100)
12811 | | // Selector of `log(string,uint256,uint256,string)`.
12812 | | mstore(0x00, 0x854b3496)
12813 | | mstore(0x20, 0x80)
12814 | | mstore(0x40, p1)
12815 | | mstore(0x60, p2)
12816 | | mstore(0x80, 0xc0)
12817 | | writeString(0xa0, p0)
12818 | | writeString(0xe0, p3)
12819 | | }
12820 | | _sendLogPayload(0x1c, 0x104);
12821 | | /// @solidity memory-safe-assembly
12822 | | assembly {
12823 | | mstore(0x00, m0)
12824 | | mstore(0x20, m1)
12825 | | mstore(0x40, m2)
12826 | | mstore(0x60, m3)
12827 | | mstore(0x80, m4)
12828 | | mstore(0xa0, m5)
12829 | | mstore(0xc0, m6)
12830 | | mstore(0xe0, m7)
12831 | | mstore(0x100, m8)
12832 | | }
12833 | | }
12834 | |
12835 | | function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure {
12836 | | bytes32 m0;
12837 | | bytes32 m1;
12838 | | bytes32 m2;
12839 | | bytes32 m3;
12840 | | bytes32 m4;
12841 | | bytes32 m5;
12842 | | bytes32 m6;
12843 | | bytes32 m7;
12844 | | bytes32 m8;
12845 | | /// @solidity memory-safe-assembly
12846 | | assembly {
12847 | | function writeString(pos, w) {
12848 | | let length := 0
12849 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12850 | | mstore(pos, length)
12851 | | let shift := sub(256, shl(3, length))
12852 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12853 | | }
12854 | | m0 := mload(0x00)
12855 | | m1 := mload(0x20)
12856 | | m2 := mload(0x40)
12857 | | m3 := mload(0x60)
12858 | | m4 := mload(0x80)
12859 | | m5 := mload(0xa0)
12860 | | m6 := mload(0xc0)
12861 | | m7 := mload(0xe0)
12862 | | m8 := mload(0x100)
12863 | | // Selector of `log(string,uint256,string,address)`.
12864 | | mstore(0x00, 0x7c4632a4)
12865 | | mstore(0x20, 0x80)
12866 | | mstore(0x40, p1)
12867 | | mstore(0x60, 0xc0)
12868 | | mstore(0x80, p3)
12869 | | writeString(0xa0, p0)
12870 | | writeString(0xe0, p2)
12871 | | }
12872 | | _sendLogPayload(0x1c, 0x104);
12873 | | /// @solidity memory-safe-assembly
12874 | | assembly {
12875 | | mstore(0x00, m0)
12876 | | mstore(0x20, m1)
12877 | | mstore(0x40, m2)
12878 | | mstore(0x60, m3)
12879 | | mstore(0x80, m4)
12880 | | mstore(0xa0, m5)
12881 | | mstore(0xc0, m6)
12882 | | mstore(0xe0, m7)
12883 | | mstore(0x100, m8)
12884 | | }
12885 | | }
12886 | |
12887 | | function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
12888 | | bytes32 m0;
12889 | | bytes32 m1;
12890 | | bytes32 m2;
12891 | | bytes32 m3;
12892 | | bytes32 m4;
12893 | | bytes32 m5;
12894 | | bytes32 m6;
12895 | | bytes32 m7;
12896 | | bytes32 m8;
12897 | | /// @solidity memory-safe-assembly
12898 | | assembly {
12899 | | function writeString(pos, w) {
12900 | | let length := 0
12901 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12902 | | mstore(pos, length)
12903 | | let shift := sub(256, shl(3, length))
12904 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12905 | | }
12906 | | m0 := mload(0x00)
12907 | | m1 := mload(0x20)
12908 | | m2 := mload(0x40)
12909 | | m3 := mload(0x60)
12910 | | m4 := mload(0x80)
12911 | | m5 := mload(0xa0)
12912 | | m6 := mload(0xc0)
12913 | | m7 := mload(0xe0)
12914 | | m8 := mload(0x100)
12915 | | // Selector of `log(string,uint256,string,bool)`.
12916 | | mstore(0x00, 0x7d24491d)
12917 | | mstore(0x20, 0x80)
12918 | | mstore(0x40, p1)
12919 | | mstore(0x60, 0xc0)
12920 | | mstore(0x80, p3)
12921 | | writeString(0xa0, p0)
12922 | | writeString(0xe0, p2)
12923 | | }
12924 | | _sendLogPayload(0x1c, 0x104);
12925 | | /// @solidity memory-safe-assembly
12926 | | assembly {
12927 | | mstore(0x00, m0)
12928 | | mstore(0x20, m1)
12929 | | mstore(0x40, m2)
12930 | | mstore(0x60, m3)
12931 | | mstore(0x80, m4)
12932 | | mstore(0xa0, m5)
12933 | | mstore(0xc0, m6)
12934 | | mstore(0xe0, m7)
12935 | | mstore(0x100, m8)
12936 | | }
12937 | | }
12938 | |
12939 | | function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
12940 | | bytes32 m0;
12941 | | bytes32 m1;
12942 | | bytes32 m2;
12943 | | bytes32 m3;
12944 | | bytes32 m4;
12945 | | bytes32 m5;
12946 | | bytes32 m6;
12947 | | bytes32 m7;
12948 | | bytes32 m8;
12949 | | /// @solidity memory-safe-assembly
12950 | | assembly {
12951 | | function writeString(pos, w) {
12952 | | let length := 0
12953 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12954 | | mstore(pos, length)
12955 | | let shift := sub(256, shl(3, length))
12956 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12957 | | }
12958 | | m0 := mload(0x00)
12959 | | m1 := mload(0x20)
12960 | | m2 := mload(0x40)
12961 | | m3 := mload(0x60)
12962 | | m4 := mload(0x80)
12963 | | m5 := mload(0xa0)
12964 | | m6 := mload(0xc0)
12965 | | m7 := mload(0xe0)
12966 | | m8 := mload(0x100)
12967 | | // Selector of `log(string,uint256,string,uint256)`.
12968 | | mstore(0x00, 0xc67ea9d1)
12969 | | mstore(0x20, 0x80)
12970 | | mstore(0x40, p1)
12971 | | mstore(0x60, 0xc0)
12972 | | mstore(0x80, p3)
12973 | | writeString(0xa0, p0)
12974 | | writeString(0xe0, p2)
12975 | | }
12976 | | _sendLogPayload(0x1c, 0x104);
12977 | | /// @solidity memory-safe-assembly
12978 | | assembly {
12979 | | mstore(0x00, m0)
12980 | | mstore(0x20, m1)
12981 | | mstore(0x40, m2)
12982 | | mstore(0x60, m3)
12983 | | mstore(0x80, m4)
12984 | | mstore(0xa0, m5)
12985 | | mstore(0xc0, m6)
12986 | | mstore(0xe0, m7)
12987 | | mstore(0x100, m8)
12988 | | }
12989 | | }
12990 | |
12991 | | function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
12992 | | bytes32 m0;
12993 | | bytes32 m1;
12994 | | bytes32 m2;
12995 | | bytes32 m3;
12996 | | bytes32 m4;
12997 | | bytes32 m5;
12998 | | bytes32 m6;
12999 | | bytes32 m7;
13000 | | bytes32 m8;
13001 | | bytes32 m9;
13002 | | bytes32 m10;
13003 | | /// @solidity memory-safe-assembly
13004 | | assembly {
13005 | | function writeString(pos, w) {
13006 | | let length := 0
13007 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13008 | | mstore(pos, length)
13009 | | let shift := sub(256, shl(3, length))
13010 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13011 | | }
13012 | | m0 := mload(0x00)
13013 | | m1 := mload(0x20)
13014 | | m2 := mload(0x40)
13015 | | m3 := mload(0x60)
13016 | | m4 := mload(0x80)
13017 | | m5 := mload(0xa0)
13018 | | m6 := mload(0xc0)
13019 | | m7 := mload(0xe0)
13020 | | m8 := mload(0x100)
13021 | | m9 := mload(0x120)
13022 | | m10 := mload(0x140)
13023 | | // Selector of `log(string,uint256,string,string)`.
13024 | | mstore(0x00, 0x5ab84e1f)
13025 | | mstore(0x20, 0x80)
13026 | | mstore(0x40, p1)
13027 | | mstore(0x60, 0xc0)
13028 | | mstore(0x80, 0x100)
13029 | | writeString(0xa0, p0)
13030 | | writeString(0xe0, p2)
13031 | | writeString(0x120, p3)
13032 | | }
13033 | | _sendLogPayload(0x1c, 0x144);
13034 | | /// @solidity memory-safe-assembly
13035 | | assembly {
13036 | | mstore(0x00, m0)
13037 | | mstore(0x20, m1)
13038 | | mstore(0x40, m2)
13039 | | mstore(0x60, m3)
13040 | | mstore(0x80, m4)
13041 | | mstore(0xa0, m5)
13042 | | mstore(0xc0, m6)
13043 | | mstore(0xe0, m7)
13044 | | mstore(0x100, m8)
13045 | | mstore(0x120, m9)
13046 | | mstore(0x140, m10)
13047 | | }
13048 | | }
13049 | |
13050 | | function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure {
13051 | | bytes32 m0;
13052 | | bytes32 m1;
13053 | | bytes32 m2;
13054 | | bytes32 m3;
13055 | | bytes32 m4;
13056 | | bytes32 m5;
13057 | | bytes32 m6;
13058 | | bytes32 m7;
13059 | | bytes32 m8;
13060 | | /// @solidity memory-safe-assembly
13061 | | assembly {
13062 | | function writeString(pos, w) {
13063 | | let length := 0
13064 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13065 | | mstore(pos, length)
13066 | | let shift := sub(256, shl(3, length))
13067 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13068 | | }
13069 | | m0 := mload(0x00)
13070 | | m1 := mload(0x20)
13071 | | m2 := mload(0x40)
13072 | | m3 := mload(0x60)
13073 | | m4 := mload(0x80)
13074 | | m5 := mload(0xa0)
13075 | | m6 := mload(0xc0)
13076 | | m7 := mload(0xe0)
13077 | | m8 := mload(0x100)
13078 | | // Selector of `log(string,string,address,address)`.
13079 | | mstore(0x00, 0x439c7bef)
13080 | | mstore(0x20, 0x80)
13081 | | mstore(0x40, 0xc0)
13082 | | mstore(0x60, p2)
13083 | | mstore(0x80, p3)
13084 | | writeString(0xa0, p0)
13085 | | writeString(0xe0, p1)
13086 | | }
13087 | | _sendLogPayload(0x1c, 0x104);
13088 | | /// @solidity memory-safe-assembly
13089 | | assembly {
13090 | | mstore(0x00, m0)
13091 | | mstore(0x20, m1)
13092 | | mstore(0x40, m2)
13093 | | mstore(0x60, m3)
13094 | | mstore(0x80, m4)
13095 | | mstore(0xa0, m5)
13096 | | mstore(0xc0, m6)
13097 | | mstore(0xe0, m7)
13098 | | mstore(0x100, m8)
13099 | | }
13100 | | }
13101 | |
13102 | | function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure {
13103 | | bytes32 m0;
13104 | | bytes32 m1;
13105 | | bytes32 m2;
13106 | | bytes32 m3;
13107 | | bytes32 m4;
13108 | | bytes32 m5;
13109 | | bytes32 m6;
13110 | | bytes32 m7;
13111 | | bytes32 m8;
13112 | | /// @solidity memory-safe-assembly
13113 | | assembly {
13114 | | function writeString(pos, w) {
13115 | | let length := 0
13116 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13117 | | mstore(pos, length)
13118 | | let shift := sub(256, shl(3, length))
13119 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13120 | | }
13121 | | m0 := mload(0x00)
13122 | | m1 := mload(0x20)
13123 | | m2 := mload(0x40)
13124 | | m3 := mload(0x60)
13125 | | m4 := mload(0x80)
13126 | | m5 := mload(0xa0)
13127 | | m6 := mload(0xc0)
13128 | | m7 := mload(0xe0)
13129 | | m8 := mload(0x100)
13130 | | // Selector of `log(string,string,address,bool)`.
13131 | | mstore(0x00, 0x5ccd4e37)
13132 | | mstore(0x20, 0x80)
13133 | | mstore(0x40, 0xc0)
13134 | | mstore(0x60, p2)
13135 | | mstore(0x80, p3)
13136 | | writeString(0xa0, p0)
13137 | | writeString(0xe0, p1)
13138 | | }
13139 | | _sendLogPayload(0x1c, 0x104);
13140 | | /// @solidity memory-safe-assembly
13141 | | assembly {
13142 | | mstore(0x00, m0)
13143 | | mstore(0x20, m1)
13144 | | mstore(0x40, m2)
13145 | | mstore(0x60, m3)
13146 | | mstore(0x80, m4)
13147 | | mstore(0xa0, m5)
13148 | | mstore(0xc0, m6)
13149 | | mstore(0xe0, m7)
13150 | | mstore(0x100, m8)
13151 | | }
13152 | | }
13153 | |
13154 | | function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure {
13155 | | bytes32 m0;
13156 | | bytes32 m1;
13157 | | bytes32 m2;
13158 | | bytes32 m3;
13159 | | bytes32 m4;
13160 | | bytes32 m5;
13161 | | bytes32 m6;
13162 | | bytes32 m7;
13163 | | bytes32 m8;
13164 | | /// @solidity memory-safe-assembly
13165 | | assembly {
13166 | | function writeString(pos, w) {
13167 | | let length := 0
13168 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13169 | | mstore(pos, length)
13170 | | let shift := sub(256, shl(3, length))
13171 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13172 | | }
13173 | | m0 := mload(0x00)
13174 | | m1 := mload(0x20)
13175 | | m2 := mload(0x40)
13176 | | m3 := mload(0x60)
13177 | | m4 := mload(0x80)
13178 | | m5 := mload(0xa0)
13179 | | m6 := mload(0xc0)
13180 | | m7 := mload(0xe0)
13181 | | m8 := mload(0x100)
13182 | | // Selector of `log(string,string,address,uint256)`.
13183 | | mstore(0x00, 0x7cc3c607)
13184 | | mstore(0x20, 0x80)
13185 | | mstore(0x40, 0xc0)
13186 | | mstore(0x60, p2)
13187 | | mstore(0x80, p3)
13188 | | writeString(0xa0, p0)
13189 | | writeString(0xe0, p1)
13190 | | }
13191 | | _sendLogPayload(0x1c, 0x104);
13192 | | /// @solidity memory-safe-assembly
13193 | | assembly {
13194 | | mstore(0x00, m0)
13195 | | mstore(0x20, m1)
13196 | | mstore(0x40, m2)
13197 | | mstore(0x60, m3)
13198 | | mstore(0x80, m4)
13199 | | mstore(0xa0, m5)
13200 | | mstore(0xc0, m6)
13201 | | mstore(0xe0, m7)
13202 | | mstore(0x100, m8)
13203 | | }
13204 | | }
13205 | |
13206 | | function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
13207 | | bytes32 m0;
13208 | | bytes32 m1;
13209 | | bytes32 m2;
13210 | | bytes32 m3;
13211 | | bytes32 m4;
13212 | | bytes32 m5;
13213 | | bytes32 m6;
13214 | | bytes32 m7;
13215 | | bytes32 m8;
13216 | | bytes32 m9;
13217 | | bytes32 m10;
13218 | | /// @solidity memory-safe-assembly
13219 | | assembly {
13220 | | function writeString(pos, w) {
13221 | | let length := 0
13222 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13223 | | mstore(pos, length)
13224 | | let shift := sub(256, shl(3, length))
13225 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13226 | | }
13227 | | m0 := mload(0x00)
13228 | | m1 := mload(0x20)
13229 | | m2 := mload(0x40)
13230 | | m3 := mload(0x60)
13231 | | m4 := mload(0x80)
13232 | | m5 := mload(0xa0)
13233 | | m6 := mload(0xc0)
13234 | | m7 := mload(0xe0)
13235 | | m8 := mload(0x100)
13236 | | m9 := mload(0x120)
13237 | | m10 := mload(0x140)
13238 | | // Selector of `log(string,string,address,string)`.
13239 | | mstore(0x00, 0xeb1bff80)
13240 | | mstore(0x20, 0x80)
13241 | | mstore(0x40, 0xc0)
13242 | | mstore(0x60, p2)
13243 | | mstore(0x80, 0x100)
13244 | | writeString(0xa0, p0)
13245 | | writeString(0xe0, p1)
13246 | | writeString(0x120, p3)
13247 | | }
13248 | | _sendLogPayload(0x1c, 0x144);
13249 | | /// @solidity memory-safe-assembly
13250 | | assembly {
13251 | | mstore(0x00, m0)
13252 | | mstore(0x20, m1)
13253 | | mstore(0x40, m2)
13254 | | mstore(0x60, m3)
13255 | | mstore(0x80, m4)
13256 | | mstore(0xa0, m5)
13257 | | mstore(0xc0, m6)
13258 | | mstore(0xe0, m7)
13259 | | mstore(0x100, m8)
13260 | | mstore(0x120, m9)
13261 | | mstore(0x140, m10)
13262 | | }
13263 | | }
13264 | |
13265 | | function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure {
13266 | | bytes32 m0;
13267 | | bytes32 m1;
13268 | | bytes32 m2;
13269 | | bytes32 m3;
13270 | | bytes32 m4;
13271 | | bytes32 m5;
13272 | | bytes32 m6;
13273 | | bytes32 m7;
13274 | | bytes32 m8;
13275 | | /// @solidity memory-safe-assembly
13276 | | assembly {
13277 | | function writeString(pos, w) {
13278 | | let length := 0
13279 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13280 | | mstore(pos, length)
13281 | | let shift := sub(256, shl(3, length))
13282 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13283 | | }
13284 | | m0 := mload(0x00)
13285 | | m1 := mload(0x20)
13286 | | m2 := mload(0x40)
13287 | | m3 := mload(0x60)
13288 | | m4 := mload(0x80)
13289 | | m5 := mload(0xa0)
13290 | | m6 := mload(0xc0)
13291 | | m7 := mload(0xe0)
13292 | | m8 := mload(0x100)
13293 | | // Selector of `log(string,string,bool,address)`.
13294 | | mstore(0x00, 0xc371c7db)
13295 | | mstore(0x20, 0x80)
13296 | | mstore(0x40, 0xc0)
13297 | | mstore(0x60, p2)
13298 | | mstore(0x80, p3)
13299 | | writeString(0xa0, p0)
13300 | | writeString(0xe0, p1)
13301 | | }
13302 | | _sendLogPayload(0x1c, 0x104);
13303 | | /// @solidity memory-safe-assembly
13304 | | assembly {
13305 | | mstore(0x00, m0)
13306 | | mstore(0x20, m1)
13307 | | mstore(0x40, m2)
13308 | | mstore(0x60, m3)
13309 | | mstore(0x80, m4)
13310 | | mstore(0xa0, m5)
13311 | | mstore(0xc0, m6)
13312 | | mstore(0xe0, m7)
13313 | | mstore(0x100, m8)
13314 | | }
13315 | | }
13316 | |
13317 | | function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure {
13318 | | bytes32 m0;
13319 | | bytes32 m1;
13320 | | bytes32 m2;
13321 | | bytes32 m3;
13322 | | bytes32 m4;
13323 | | bytes32 m5;
13324 | | bytes32 m6;
13325 | | bytes32 m7;
13326 | | bytes32 m8;
13327 | | /// @solidity memory-safe-assembly
13328 | | assembly {
13329 | | function writeString(pos, w) {
13330 | | let length := 0
13331 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13332 | | mstore(pos, length)
13333 | | let shift := sub(256, shl(3, length))
13334 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13335 | | }
13336 | | m0 := mload(0x00)
13337 | | m1 := mload(0x20)
13338 | | m2 := mload(0x40)
13339 | | m3 := mload(0x60)
13340 | | m4 := mload(0x80)
13341 | | m5 := mload(0xa0)
13342 | | m6 := mload(0xc0)
13343 | | m7 := mload(0xe0)
13344 | | m8 := mload(0x100)
13345 | | // Selector of `log(string,string,bool,bool)`.
13346 | | mstore(0x00, 0x40785869)
13347 | | mstore(0x20, 0x80)
13348 | | mstore(0x40, 0xc0)
13349 | | mstore(0x60, p2)
13350 | | mstore(0x80, p3)
13351 | | writeString(0xa0, p0)
13352 | | writeString(0xe0, p1)
13353 | | }
13354 | | _sendLogPayload(0x1c, 0x104);
13355 | | /// @solidity memory-safe-assembly
13356 | | assembly {
13357 | | mstore(0x00, m0)
13358 | | mstore(0x20, m1)
13359 | | mstore(0x40, m2)
13360 | | mstore(0x60, m3)
13361 | | mstore(0x80, m4)
13362 | | mstore(0xa0, m5)
13363 | | mstore(0xc0, m6)
13364 | | mstore(0xe0, m7)
13365 | | mstore(0x100, m8)
13366 | | }
13367 | | }
13368 | |
13369 | | function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
13370 | | bytes32 m0;
13371 | | bytes32 m1;
13372 | | bytes32 m2;
13373 | | bytes32 m3;
13374 | | bytes32 m4;
13375 | | bytes32 m5;
13376 | | bytes32 m6;
13377 | | bytes32 m7;
13378 | | bytes32 m8;
13379 | | /// @solidity memory-safe-assembly
13380 | | assembly {
13381 | | function writeString(pos, w) {
13382 | | let length := 0
13383 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13384 | | mstore(pos, length)
13385 | | let shift := sub(256, shl(3, length))
13386 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13387 | | }
13388 | | m0 := mload(0x00)
13389 | | m1 := mload(0x20)
13390 | | m2 := mload(0x40)
13391 | | m3 := mload(0x60)
13392 | | m4 := mload(0x80)
13393 | | m5 := mload(0xa0)
13394 | | m6 := mload(0xc0)
13395 | | m7 := mload(0xe0)
13396 | | m8 := mload(0x100)
13397 | | // Selector of `log(string,string,bool,uint256)`.
13398 | | mstore(0x00, 0xd6aefad2)
13399 | | mstore(0x20, 0x80)
13400 | | mstore(0x40, 0xc0)
13401 | | mstore(0x60, p2)
13402 | | mstore(0x80, p3)
13403 | | writeString(0xa0, p0)
13404 | | writeString(0xe0, p1)
13405 | | }
13406 | | _sendLogPayload(0x1c, 0x104);
13407 | | /// @solidity memory-safe-assembly
13408 | | assembly {
13409 | | mstore(0x00, m0)
13410 | | mstore(0x20, m1)
13411 | | mstore(0x40, m2)
13412 | | mstore(0x60, m3)
13413 | | mstore(0x80, m4)
13414 | | mstore(0xa0, m5)
13415 | | mstore(0xc0, m6)
13416 | | mstore(0xe0, m7)
13417 | | mstore(0x100, m8)
13418 | | }
13419 | | }
13420 | |
13421 | | function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
13422 | | bytes32 m0;
13423 | | bytes32 m1;
13424 | | bytes32 m2;
13425 | | bytes32 m3;
13426 | | bytes32 m4;
13427 | | bytes32 m5;
13428 | | bytes32 m6;
13429 | | bytes32 m7;
13430 | | bytes32 m8;
13431 | | bytes32 m9;
13432 | | bytes32 m10;
13433 | | /// @solidity memory-safe-assembly
13434 | | assembly {
13435 | | function writeString(pos, w) {
13436 | | let length := 0
13437 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13438 | | mstore(pos, length)
13439 | | let shift := sub(256, shl(3, length))
13440 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13441 | | }
13442 | | m0 := mload(0x00)
13443 | | m1 := mload(0x20)
13444 | | m2 := mload(0x40)
13445 | | m3 := mload(0x60)
13446 | | m4 := mload(0x80)
13447 | | m5 := mload(0xa0)
13448 | | m6 := mload(0xc0)
13449 | | m7 := mload(0xe0)
13450 | | m8 := mload(0x100)
13451 | | m9 := mload(0x120)
13452 | | m10 := mload(0x140)
13453 | | // Selector of `log(string,string,bool,string)`.
13454 | | mstore(0x00, 0x5e84b0ea)
13455 | | mstore(0x20, 0x80)
13456 | | mstore(0x40, 0xc0)
13457 | | mstore(0x60, p2)
13458 | | mstore(0x80, 0x100)
13459 | | writeString(0xa0, p0)
13460 | | writeString(0xe0, p1)
13461 | | writeString(0x120, p3)
13462 | | }
13463 | | _sendLogPayload(0x1c, 0x144);
13464 | | /// @solidity memory-safe-assembly
13465 | | assembly {
13466 | | mstore(0x00, m0)
13467 | | mstore(0x20, m1)
13468 | | mstore(0x40, m2)
13469 | | mstore(0x60, m3)
13470 | | mstore(0x80, m4)
13471 | | mstore(0xa0, m5)
13472 | | mstore(0xc0, m6)
13473 | | mstore(0xe0, m7)
13474 | | mstore(0x100, m8)
13475 | | mstore(0x120, m9)
13476 | | mstore(0x140, m10)
13477 | | }
13478 | | }
13479 | |
13480 | | function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure {
13481 | | bytes32 m0;
13482 | | bytes32 m1;
13483 | | bytes32 m2;
13484 | | bytes32 m3;
13485 | | bytes32 m4;
13486 | | bytes32 m5;
13487 | | bytes32 m6;
13488 | | bytes32 m7;
13489 | | bytes32 m8;
13490 | | /// @solidity memory-safe-assembly
13491 | | assembly {
13492 | | function writeString(pos, w) {
13493 | | let length := 0
13494 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13495 | | mstore(pos, length)
13496 | | let shift := sub(256, shl(3, length))
13497 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13498 | | }
13499 | | m0 := mload(0x00)
13500 | | m1 := mload(0x20)
13501 | | m2 := mload(0x40)
13502 | | m3 := mload(0x60)
13503 | | m4 := mload(0x80)
13504 | | m5 := mload(0xa0)
13505 | | m6 := mload(0xc0)
13506 | | m7 := mload(0xe0)
13507 | | m8 := mload(0x100)
13508 | | // Selector of `log(string,string,uint256,address)`.
13509 | | mstore(0x00, 0x1023f7b2)
13510 | | mstore(0x20, 0x80)
13511 | | mstore(0x40, 0xc0)
13512 | | mstore(0x60, p2)
13513 | | mstore(0x80, p3)
13514 | | writeString(0xa0, p0)
13515 | | writeString(0xe0, p1)
13516 | | }
13517 | | _sendLogPayload(0x1c, 0x104);
13518 | | /// @solidity memory-safe-assembly
13519 | | assembly {
13520 | | mstore(0x00, m0)
13521 | | mstore(0x20, m1)
13522 | | mstore(0x40, m2)
13523 | | mstore(0x60, m3)
13524 | | mstore(0x80, m4)
13525 | | mstore(0xa0, m5)
13526 | | mstore(0xc0, m6)
13527 | | mstore(0xe0, m7)
13528 | | mstore(0x100, m8)
13529 | | }
13530 | | }
13531 | |
13532 | | function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
13533 | | bytes32 m0;
13534 | | bytes32 m1;
13535 | | bytes32 m2;
13536 | | bytes32 m3;
13537 | | bytes32 m4;
13538 | | bytes32 m5;
13539 | | bytes32 m6;
13540 | | bytes32 m7;
13541 | | bytes32 m8;
13542 | | /// @solidity memory-safe-assembly
13543 | | assembly {
13544 | | function writeString(pos, w) {
13545 | | let length := 0
13546 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13547 | | mstore(pos, length)
13548 | | let shift := sub(256, shl(3, length))
13549 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13550 | | }
13551 | | m0 := mload(0x00)
13552 | | m1 := mload(0x20)
13553 | | m2 := mload(0x40)
13554 | | m3 := mload(0x60)
13555 | | m4 := mload(0x80)
13556 | | m5 := mload(0xa0)
13557 | | m6 := mload(0xc0)
13558 | | m7 := mload(0xe0)
13559 | | m8 := mload(0x100)
13560 | | // Selector of `log(string,string,uint256,bool)`.
13561 | | mstore(0x00, 0xc3a8a654)
13562 | | mstore(0x20, 0x80)
13563 | | mstore(0x40, 0xc0)
13564 | | mstore(0x60, p2)
13565 | | mstore(0x80, p3)
13566 | | writeString(0xa0, p0)
13567 | | writeString(0xe0, p1)
13568 | | }
13569 | | _sendLogPayload(0x1c, 0x104);
13570 | | /// @solidity memory-safe-assembly
13571 | | assembly {
13572 | | mstore(0x00, m0)
13573 | | mstore(0x20, m1)
13574 | | mstore(0x40, m2)
13575 | | mstore(0x60, m3)
13576 | | mstore(0x80, m4)
13577 | | mstore(0xa0, m5)
13578 | | mstore(0xc0, m6)
13579 | | mstore(0xe0, m7)
13580 | | mstore(0x100, m8)
13581 | | }
13582 | | }
13583 | |
13584 | | function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
13585 | | bytes32 m0;
13586 | | bytes32 m1;
13587 | | bytes32 m2;
13588 | | bytes32 m3;
13589 | | bytes32 m4;
13590 | | bytes32 m5;
13591 | | bytes32 m6;
13592 | | bytes32 m7;
13593 | | bytes32 m8;
13594 | | /// @solidity memory-safe-assembly
13595 | | assembly {
13596 | | function writeString(pos, w) {
13597 | | let length := 0
13598 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13599 | | mstore(pos, length)
13600 | | let shift := sub(256, shl(3, length))
13601 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13602 | | }
13603 | | m0 := mload(0x00)
13604 | | m1 := mload(0x20)
13605 | | m2 := mload(0x40)
13606 | | m3 := mload(0x60)
13607 | | m4 := mload(0x80)
13608 | | m5 := mload(0xa0)
13609 | | m6 := mload(0xc0)
13610 | | m7 := mload(0xe0)
13611 | | m8 := mload(0x100)
13612 | | // Selector of `log(string,string,uint256,uint256)`.
13613 | | mstore(0x00, 0xf45d7d2c)
13614 | | mstore(0x20, 0x80)
13615 | | mstore(0x40, 0xc0)
13616 | | mstore(0x60, p2)
13617 | | mstore(0x80, p3)
13618 | | writeString(0xa0, p0)
13619 | | writeString(0xe0, p1)
13620 | | }
13621 | | _sendLogPayload(0x1c, 0x104);
13622 | | /// @solidity memory-safe-assembly
13623 | | assembly {
13624 | | mstore(0x00, m0)
13625 | | mstore(0x20, m1)
13626 | | mstore(0x40, m2)
13627 | | mstore(0x60, m3)
13628 | | mstore(0x80, m4)
13629 | | mstore(0xa0, m5)
13630 | | mstore(0xc0, m6)
13631 | | mstore(0xe0, m7)
13632 | | mstore(0x100, m8)
13633 | | }
13634 | | }
13635 | |
13636 | | function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
13637 | | bytes32 m0;
13638 | | bytes32 m1;
13639 | | bytes32 m2;
13640 | | bytes32 m3;
13641 | | bytes32 m4;
13642 | | bytes32 m5;
13643 | | bytes32 m6;
13644 | | bytes32 m7;
13645 | | bytes32 m8;
13646 | | bytes32 m9;
13647 | | bytes32 m10;
13648 | | /// @solidity memory-safe-assembly
13649 | | assembly {
13650 | | function writeString(pos, w) {
13651 | | let length := 0
13652 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13653 | | mstore(pos, length)
13654 | | let shift := sub(256, shl(3, length))
13655 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13656 | | }
13657 | | m0 := mload(0x00)
13658 | | m1 := mload(0x20)
13659 | | m2 := mload(0x40)
13660 | | m3 := mload(0x60)
13661 | | m4 := mload(0x80)
13662 | | m5 := mload(0xa0)
13663 | | m6 := mload(0xc0)
13664 | | m7 := mload(0xe0)
13665 | | m8 := mload(0x100)
13666 | | m9 := mload(0x120)
13667 | | m10 := mload(0x140)
13668 | | // Selector of `log(string,string,uint256,string)`.
13669 | | mstore(0x00, 0x5d1a971a)
13670 | | mstore(0x20, 0x80)
13671 | | mstore(0x40, 0xc0)
13672 | | mstore(0x60, p2)
13673 | | mstore(0x80, 0x100)
13674 | | writeString(0xa0, p0)
13675 | | writeString(0xe0, p1)
13676 | | writeString(0x120, p3)
13677 | | }
13678 | | _sendLogPayload(0x1c, 0x144);
13679 | | /// @solidity memory-safe-assembly
13680 | | assembly {
13681 | | mstore(0x00, m0)
13682 | | mstore(0x20, m1)
13683 | | mstore(0x40, m2)
13684 | | mstore(0x60, m3)
13685 | | mstore(0x80, m4)
13686 | | mstore(0xa0, m5)
13687 | | mstore(0xc0, m6)
13688 | | mstore(0xe0, m7)
13689 | | mstore(0x100, m8)
13690 | | mstore(0x120, m9)
13691 | | mstore(0x140, m10)
13692 | | }
13693 | | }
13694 | |
13695 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
13696 | | bytes32 m0;
13697 | | bytes32 m1;
13698 | | bytes32 m2;
13699 | | bytes32 m3;
13700 | | bytes32 m4;
13701 | | bytes32 m5;
13702 | | bytes32 m6;
13703 | | bytes32 m7;
13704 | | bytes32 m8;
13705 | | bytes32 m9;
13706 | | bytes32 m10;
13707 | | /// @solidity memory-safe-assembly
13708 | | assembly {
13709 | | function writeString(pos, w) {
13710 | | let length := 0
13711 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13712 | | mstore(pos, length)
13713 | | let shift := sub(256, shl(3, length))
13714 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13715 | | }
13716 | | m0 := mload(0x00)
13717 | | m1 := mload(0x20)
13718 | | m2 := mload(0x40)
13719 | | m3 := mload(0x60)
13720 | | m4 := mload(0x80)
13721 | | m5 := mload(0xa0)
13722 | | m6 := mload(0xc0)
13723 | | m7 := mload(0xe0)
13724 | | m8 := mload(0x100)
13725 | | m9 := mload(0x120)
13726 | | m10 := mload(0x140)
13727 | | // Selector of `log(string,string,string,address)`.
13728 | | mstore(0x00, 0x6d572f44)
13729 | | mstore(0x20, 0x80)
13730 | | mstore(0x40, 0xc0)
13731 | | mstore(0x60, 0x100)
13732 | | mstore(0x80, p3)
13733 | | writeString(0xa0, p0)
13734 | | writeString(0xe0, p1)
13735 | | writeString(0x120, p2)
13736 | | }
13737 | | _sendLogPayload(0x1c, 0x144);
13738 | | /// @solidity memory-safe-assembly
13739 | | assembly {
13740 | | mstore(0x00, m0)
13741 | | mstore(0x20, m1)
13742 | | mstore(0x40, m2)
13743 | | mstore(0x60, m3)
13744 | | mstore(0x80, m4)
13745 | | mstore(0xa0, m5)
13746 | | mstore(0xc0, m6)
13747 | | mstore(0xe0, m7)
13748 | | mstore(0x100, m8)
13749 | | mstore(0x120, m9)
13750 | | mstore(0x140, m10)
13751 | | }
13752 | | }
13753 | |
13754 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
13755 | | bytes32 m0;
13756 | | bytes32 m1;
13757 | | bytes32 m2;
13758 | | bytes32 m3;
13759 | | bytes32 m4;
13760 | | bytes32 m5;
13761 | | bytes32 m6;
13762 | | bytes32 m7;
13763 | | bytes32 m8;
13764 | | bytes32 m9;
13765 | | bytes32 m10;
13766 | | /// @solidity memory-safe-assembly
13767 | | assembly {
13768 | | function writeString(pos, w) {
13769 | | let length := 0
13770 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13771 | | mstore(pos, length)
13772 | | let shift := sub(256, shl(3, length))
13773 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13774 | | }
13775 | | m0 := mload(0x00)
13776 | | m1 := mload(0x20)
13777 | | m2 := mload(0x40)
13778 | | m3 := mload(0x60)
13779 | | m4 := mload(0x80)
13780 | | m5 := mload(0xa0)
13781 | | m6 := mload(0xc0)
13782 | | m7 := mload(0xe0)
13783 | | m8 := mload(0x100)
13784 | | m9 := mload(0x120)
13785 | | m10 := mload(0x140)
13786 | | // Selector of `log(string,string,string,bool)`.
13787 | | mstore(0x00, 0x2c1754ed)
13788 | | mstore(0x20, 0x80)
13789 | | mstore(0x40, 0xc0)
13790 | | mstore(0x60, 0x100)
13791 | | mstore(0x80, p3)
13792 | | writeString(0xa0, p0)
13793 | | writeString(0xe0, p1)
13794 | | writeString(0x120, p2)
13795 | | }
13796 | | _sendLogPayload(0x1c, 0x144);
13797 | | /// @solidity memory-safe-assembly
13798 | | assembly {
13799 | | mstore(0x00, m0)
13800 | | mstore(0x20, m1)
13801 | | mstore(0x40, m2)
13802 | | mstore(0x60, m3)
13803 | | mstore(0x80, m4)
13804 | | mstore(0xa0, m5)
13805 | | mstore(0xc0, m6)
13806 | | mstore(0xe0, m7)
13807 | | mstore(0x100, m8)
13808 | | mstore(0x120, m9)
13809 | | mstore(0x140, m10)
13810 | | }
13811 | | }
13812 | |
13813 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
13814 | | bytes32 m0;
13815 | | bytes32 m1;
13816 | | bytes32 m2;
13817 | | bytes32 m3;
13818 | | bytes32 m4;
13819 | | bytes32 m5;
13820 | | bytes32 m6;
13821 | | bytes32 m7;
13822 | | bytes32 m8;
13823 | | bytes32 m9;
13824 | | bytes32 m10;
13825 | | /// @solidity memory-safe-assembly
13826 | | assembly {
13827 | | function writeString(pos, w) {
13828 | | let length := 0
13829 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13830 | | mstore(pos, length)
13831 | | let shift := sub(256, shl(3, length))
13832 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13833 | | }
13834 | | m0 := mload(0x00)
13835 | | m1 := mload(0x20)
13836 | | m2 := mload(0x40)
13837 | | m3 := mload(0x60)
13838 | | m4 := mload(0x80)
13839 | | m5 := mload(0xa0)
13840 | | m6 := mload(0xc0)
13841 | | m7 := mload(0xe0)
13842 | | m8 := mload(0x100)
13843 | | m9 := mload(0x120)
13844 | | m10 := mload(0x140)
13845 | | // Selector of `log(string,string,string,uint256)`.
13846 | | mstore(0x00, 0x8eafb02b)
13847 | | mstore(0x20, 0x80)
13848 | | mstore(0x40, 0xc0)
13849 | | mstore(0x60, 0x100)
13850 | | mstore(0x80, p3)
13851 | | writeString(0xa0, p0)
13852 | | writeString(0xe0, p1)
13853 | | writeString(0x120, p2)
13854 | | }
13855 | | _sendLogPayload(0x1c, 0x144);
13856 | | /// @solidity memory-safe-assembly
13857 | | assembly {
13858 | | mstore(0x00, m0)
13859 | | mstore(0x20, m1)
13860 | | mstore(0x40, m2)
13861 | | mstore(0x60, m3)
13862 | | mstore(0x80, m4)
13863 | | mstore(0xa0, m5)
13864 | | mstore(0xc0, m6)
13865 | | mstore(0xe0, m7)
13866 | | mstore(0x100, m8)
13867 | | mstore(0x120, m9)
13868 | | mstore(0x140, m10)
13869 | | }
13870 | | }
13871 | |
13872 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
13873 | | bytes32 m0;
13874 | | bytes32 m1;
13875 | | bytes32 m2;
13876 | | bytes32 m3;
13877 | | bytes32 m4;
13878 | | bytes32 m5;
13879 | | bytes32 m6;
13880 | | bytes32 m7;
13881 | | bytes32 m8;
13882 | | bytes32 m9;
13883 | | bytes32 m10;
13884 | | bytes32 m11;
13885 | | bytes32 m12;
13886 | | /// @solidity memory-safe-assembly
13887 | | assembly {
13888 | | function writeString(pos, w) {
13889 | | let length := 0
13890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13891 | | mstore(pos, length)
13892 | | let shift := sub(256, shl(3, length))
13893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13894 | | }
13895 | | m0 := mload(0x00)
13896 | | m1 := mload(0x20)
13897 | | m2 := mload(0x40)
13898 | | m3 := mload(0x60)
13899 | | m4 := mload(0x80)
13900 | | m5 := mload(0xa0)
13901 | | m6 := mload(0xc0)
13902 | | m7 := mload(0xe0)
13903 | | m8 := mload(0x100)
13904 | | m9 := mload(0x120)
13905 | | m10 := mload(0x140)
13906 | | m11 := mload(0x160)
13907 | | m12 := mload(0x180)
13908 | | // Selector of `log(string,string,string,string)`.
13909 | | mstore(0x00, 0xde68f20a)
13910 | | mstore(0x20, 0x80)
13911 | | mstore(0x40, 0xc0)
13912 | | mstore(0x60, 0x100)
13913 | | mstore(0x80, 0x140)
13914 | | writeString(0xa0, p0)
13915 | | writeString(0xe0, p1)
13916 | | writeString(0x120, p2)
13917 | | writeString(0x160, p3)
13918 | | }
13919 | | _sendLogPayload(0x1c, 0x184);
13920 | | /// @solidity memory-safe-assembly
13921 | | assembly {
13922 | | mstore(0x00, m0)
13923 | | mstore(0x20, m1)
13924 | | mstore(0x40, m2)
13925 | | mstore(0x60, m3)
13926 | | mstore(0x80, m4)
13927 | | mstore(0xa0, m5)
13928 | | mstore(0xc0, m6)
13929 | | mstore(0xe0, m7)
13930 | | mstore(0x100, m8)
13931 | | mstore(0x120, m9)
13932 | | mstore(0x140, m10)
13933 | | mstore(0x160, m11)
13934 | | mstore(0x180, m12)
13935 | | }
13936 | | }
13937 | | }
13938 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/Constants.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | library Constants {
5 | | // https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require
6 | | // 0x00: Used for generic compiler inserted panics.
7 | | // 0x01: If you call assert with an argument that evaluates to false.
8 | | // 0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block.
9 | | // 0x12; If you divide or modulo by zero (e.g. 5 / 0 or 23 % 0).
10 | | // 0x21: If you convert a value that is too big or negative into an enum type.
11 | | // 0x22: If you access a storage byte array that is incorrectly encoded.
12 | | // 0x31: If you call .pop() on an empty array.
13 | | // 0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0).
14 | | // 0x41: If you allocate too much memory or create an array that is too large.
15 | | // 0x51: If you call a zero-initialized variable of internal function type.
16 | | uint256 public constant PANIC_GENERAL = 0x00;
17 | | uint256 public constant PANIC_ASSERT = 0x01;
18 | | uint256 public constant PANIC_ARITHMETIC = 0x11;
19 | | uint256 public constant PANIC_DIVISION_BY_ZERO = 0x12;
20 | | uint256 public constant PANIC_ENUM_OUT_OF_BOUNDS = 0x21;
21 | | uint256 public constant PANIC_STORAGE_BYTES_ARRAY_ENCODING = 0x22;
22 | | uint256 public constant PANIC_POP_EMPTY_ARRAY = 0x31;
23 | | uint256 public constant PANIC_ARRAY_OUT_OF_BOUNDS = 0x32;
24 | | uint256 public constant PANIC_ALLOC_TOO_MUCH_MEMORY = 0x41;
25 | | uint256 public constant PANIC_ZERO_INIT_INTERNAL_FUNCTION = 0x51;
26 | |
27 | | address public constant ADDRESS_CHEATS =
28 | | 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/FuzzBase.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {Fuzzlib} from "./Fuzzlib.sol";
5 | | import {PlatformCrytic} from "./platform/PlatformCrytic.sol";
6 | |
7 | | abstract contract FuzzBase {
8 | | Fuzzlib internal fl = new Fuzzlib();
9 | |
10 | | constructor() {
11 | | fl.setPlatform(address(new PlatformCrytic()));
12 | | }
13 | | }
14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/FuzzLibString.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | /// @notice Efficient library for creating string representations of integers.
5 | | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
6 | | /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
7 | | /// @author Modified from Crytic Properties (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol)
8 | * | library FuzzLibString {
9 | | bytes16 internal constant HEX_DIGITS = "0123456789abcdef";
10 | |
11 | | function toString(int256 value) internal pure returns (string memory str) {
12 | | uint256 absValue = value >= 0 ? uint256(value) : uint256(-value);
13 | | str = toString(absValue);
14 | |
15 | | if (value < 0) {
16 | | str = string(abi.encodePacked("-", str));
17 | | }
18 | | }
19 | |
20 | * | function toString(uint256 value) internal pure returns (string memory str) {
21 | | /// @solidity memory-safe-assembly
22 | * | assembly {
23 | | // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
24 | | // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
25 | | // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
26 | * | let newFreeMemoryPointer := add(mload(0x40), 160)
27 | |
28 | | // Update the free memory pointer to avoid overriding our string.
29 | * | mstore(0x40, newFreeMemoryPointer)
30 | |
31 | | // Assign str to the end of the zone of newly allocated memory.
32 | * | str := sub(newFreeMemoryPointer, 32)
33 | |
34 | | // Clean the last word of memory it may not be overwritten.
35 | * | mstore(str, 0)
36 | |
37 | | // Cache the end of the memory to calculate the length later.
38 | * | let end := str
39 | |
40 | | // We write the string from rightmost digit to leftmost digit.
41 | | // The following is essentially a do-while loop that also handles the zero case.
42 | | // prettier-ignore
43 | * | for { let temp := value } 1 {} {
44 | | // Move the pointer 1 byte to the left.
45 | * | str := sub(str, 1)
46 | |
47 | | // Write the character to the pointer.
48 | | // The ASCII index of the '0' character is 48.
49 | * | mstore8(str, add(48, mod(temp, 10)))
50 | |
51 | | // Keep dividing temp until zero.
52 | * | temp := div(temp, 10)
53 | |
54 | | // prettier-ignore
55 | * | if iszero(temp) { break }
56 | | }
57 | |
58 | | // Compute and cache the final total length of the string.
59 | * | let length := sub(end, str)
60 | |
61 | | // Move the pointer 32 bytes leftwards to make room for the length.
62 | * | str := sub(str, 32)
63 | |
64 | | // Store the string's length at the start of memory allocated for our string.
65 | * | mstore(str, length)
66 | | }
67 | | }
68 | |
69 | | function toString(address value) internal pure returns (string memory str) {
70 | | bytes memory s = new bytes(40);
71 | | for (uint256 i = 0; i < 20; i++) {
72 | | bytes1 b = bytes1(
73 | | uint8(uint256(uint160(value)) / (2**(8 * (19 - i))))
74 | | );
75 | | bytes1 hi = bytes1(uint8(b) / 16);
76 | | bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
77 | | s[2 * i] = char(hi);
78 | | s[2 * i + 1] = char(lo);
79 | | }
80 | | return string(s);
81 | | }
82 | |
83 | | function char(bytes1 b) internal pure returns (bytes1 c) {
84 | | if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
85 | | else return bytes1(uint8(b) + 0x57);
86 | | }
87 | |
88 | | // based on OZ's toHexString
89 | | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol
90 | | function toHexString(bytes memory value)
91 | | internal
92 | | pure
93 | | returns (string memory)
94 | | {
95 | | bytes memory buffer = new bytes(2 * value.length + 2);
96 | | buffer[0] = "0";
97 | | buffer[1] = "x";
98 | | for (uint256 i = 0; i < value.length; i++) {
99 | | uint8 valueByte = uint8(value[i]);
100 | | buffer[2 * i + 2] = HEX_DIGITS[valueByte >> 4];
101 | | buffer[2 * i + 3] = HEX_DIGITS[valueByte & 0xf];
102 | | }
103 | | return string(buffer);
104 | | }
105 | |
106 | | // https://ethereum.stackexchange.com/a/83577
107 | | function getRevertMsg(bytes memory returnData)
108 | | internal
109 | | pure
110 | | returns (string memory)
111 | | {
112 | | // Check that the data has the right size: 4 bytes for signature + 32 bytes for panic code
113 | | if (returnData.length == 4 + 32) {
114 | | // Check that the data starts with the Panic signature
115 | | bytes4 panicSignature = bytes4(keccak256(bytes("Panic(uint256)")));
116 | | for (uint256 i = 0; i < 4; i++) {
117 | | if (returnData[i] != panicSignature[i])
118 | | return "Undefined signature";
119 | | }
120 | |
121 | | uint256 panicCode;
122 | | for (uint256 i = 4; i < 36; i++) {
123 | | panicCode = panicCode << 8;
124 | | panicCode |= uint8(returnData[i]);
125 | | }
126 | |
127 | | // Now convert the panic code into its string representation
128 | | if (panicCode == 17) {
129 | | return "Panic(17)";
130 | | }
131 | |
132 | | // Add other panic codes as needed or return a generic "Unknown panic"
133 | | return "Undefined panic code";
134 | | }
135 | |
136 | | // If the returnData length is less than 68, then the transaction failed silently (without a revert message)
137 | | if (returnData.length < 68) return "Transaction reverted silently";
138 | |
139 | | assembly {
140 | | // Slice the sighash.
141 | | returnData := add(returnData, 0x04)
142 | | }
143 | | return abi.decode(returnData, (string)); // All that remains is the revert string
144 | | }
145 | |
146 | | function isRevertReasonEqual(bytes memory returnData, string memory reason)
147 | | internal
148 | | pure
149 | | returns (bool)
150 | | {
151 | | return (keccak256(abi.encodePacked(getRevertMsg(returnData))) ==
152 | | keccak256(abi.encodePacked(reason)));
153 | | }
154 | | }
155 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/Fuzzlib.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {HelperBase} from "./helpers/HelperBase.sol";
5 | | import {HelperAssert} from "./helpers/HelperAssert.sol";
6 | | import {HelperClamp} from "./helpers/HelperClamp.sol";
7 | | import {HelperLog} from "./helpers/HelperLog.sol";
8 | | import {HelperMath} from "./helpers/HelperMath.sol";
9 | | import {HelperRandom} from "./helpers/HelperRandom.sol";
10 | |
11 | * | contract Fuzzlib is
12 | | HelperBase,
13 | | HelperAssert,
14 | | HelperClamp,
15 | | HelperLog,
16 | | HelperMath,
17 | | HelperRandom
18 | | {}
19 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/IHevm.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {Constants} from "./Constants.sol";
5 | |
6 | | interface IHevm {
7 | | // Set block.timestamp to newTimestamp
8 | | function warp(uint256 newTimestamp) external;
9 | |
10 | | // Set block.number to newNumber
11 | | function roll(uint256 newNumber) external;
12 | |
13 | | // Add the condition b to the assumption base for the current branch
14 | | // This function is almost identical to require
15 | | function assume(bool b) external;
16 | |
17 | | // Sets the eth balance of usr to amt
18 | | function deal(address usr, uint256 amt) external;
19 | |
20 | | // Loads a storage slot from an address
21 | | function load(address where, bytes32 slot) external returns (bytes32);
22 | |
23 | | // Stores a value to an address' storage slot
24 | | function store(address where, bytes32 slot, bytes32 value) external;
25 | |
26 | | // Signs data (privateKey, digest) => (v, r, s)
27 | | function sign(
28 | | uint256 privateKey,
29 | | bytes32 digest
30 | | ) external returns (uint8 v, bytes32 r, bytes32 s);
31 | |
32 | | // Gets address for a given private key
33 | | function addr(uint256 privateKey) external returns (address addr);
34 | |
35 | | // Performs a foreign function call via terminal
36 | | function ffi(
37 | | string[] calldata inputs
38 | | ) external returns (bytes memory result);
39 | |
40 | | // Performs the next smart contract call with specified `msg.sender`
41 | | function prank(address newSender) external;
42 | |
43 | | // Creates a new fork with the given endpoint and the latest block and returns the identifier of the fork
44 | | function createFork(string calldata urlOrAlias) external returns (uint256);
45 | |
46 | | // Takes a fork identifier created by createFork and sets the corresponding forked state as active
47 | | function selectFork(uint256 forkId) external;
48 | |
49 | | // Returns the identifier of the current fork
50 | | function activeFork() external returns (uint256);
51 | |
52 | | // Labels the address in traces
53 | | function label(address addr, string calldata label) external;
54 | | }
55 | |
56 | | // Don't use Constants.ADDRESS_CHEATS to support older Solidity versions
57 | | IHevm constant vm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
58 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperAssert.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "./HelperBase.sol";
5 | |
6 | | import "../FuzzLibString.sol";
7 | |
8 | | /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol)
9 | | abstract contract HelperAssert is HelperBase {
10 | | event AssertFail(string);
11 | | event AssertEqFail(string);
12 | | event AssertNeqFail(string);
13 | | event AssertGteFail(string);
14 | | event AssertGtFail(string);
15 | | event AssertLteFail(string);
16 | | event AssertLtFail(string);
17 | |
18 | * | function t(bool b, string memory reason) public {
19 | * | if (!b) {
20 | * | emit AssertFail(reason);
21 | * | platform.assertFail();
22 | | }
23 | | }
24 | |
25 | | /// @notice asserts that a is equal to b. Violations are logged using reason.
26 | * | function eq(
27 | | uint256 a,
28 | | uint256 b,
29 | | string memory reason
30 | | ) public {
31 | * | if (a != b) {
32 | | string memory aStr = FuzzLibString.toString(a);
33 | | string memory bStr = FuzzLibString.toString(b);
34 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason);
35 | | emit AssertEqFail(assertMsg);
36 | | platform.assertFail();
37 | | }
38 | | }
39 | |
40 | | /// @notice int256 version of eq
41 | | function eq(
42 | | int256 a,
43 | | int256 b,
44 | | string memory reason
45 | | ) public {
46 | | if (a != b) {
47 | | string memory aStr = FuzzLibString.toString(a);
48 | | string memory bStr = FuzzLibString.toString(b);
49 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason);
50 | | emit AssertEqFail(assertMsg);
51 | | platform.assertFail();
52 | | }
53 | | }
54 | |
55 | | /// @notice bool version of eq
56 | | function eq(
57 | | bool a,
58 | | bool b,
59 | | string memory reason
60 | | ) public {
61 | | if (a != b) {
62 | | string memory aStr = a ? "true" : "false";
63 | | string memory bStr = b ? "true" : "false";
64 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason);
65 | | emit AssertEqFail(assertMsg);
66 | | platform.assertFail();
67 | | }
68 | | }
69 | |
70 | | /// @notice address version of eq
71 | | function eq(
72 | | address a,
73 | | address b,
74 | | string memory reason
75 | | ) public {
76 | | if (a != b) {
77 | | string memory aStr = FuzzLibString.toString(a);
78 | | string memory bStr = FuzzLibString.toString(b);
79 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason);
80 | | emit AssertEqFail(assertMsg);
81 | | platform.assertFail();
82 | | }
83 | | }
84 | |
85 | | /// @notice bytes4 version of eq
86 | | function eq(
87 | | bytes4 a,
88 | | bytes4 b,
89 | | string memory reason
90 | | ) public {
91 | | if (a != b) {
92 | | bytes memory aBytes = abi.encodePacked(a);
93 | | bytes memory bBytes = abi.encodePacked(b);
94 | | string memory aStr = FuzzLibString.toHexString(aBytes);
95 | | string memory bStr = FuzzLibString.toHexString(bBytes);
96 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason);
97 | | emit AssertEqFail(assertMsg);
98 | | platform.assertFail();
99 | | }
100 | | }
101 | |
102 | | /// @notice asserts that a is not equal to b. Violations are logged using reason.
103 | * | function neq(
104 | | uint256 a,
105 | | uint256 b,
106 | | string memory reason
107 | | ) public {
108 | * | if (a == b) {
109 | | string memory aStr = FuzzLibString.toString(a);
110 | | string memory bStr = FuzzLibString.toString(b);
111 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "==", reason);
112 | | emit AssertNeqFail(assertMsg);
113 | | platform.assertFail();
114 | | }
115 | | }
116 | |
117 | | /// @notice int256 version of neq
118 | | function neq(
119 | | int256 a,
120 | | int256 b,
121 | | string memory reason
122 | | ) public {
123 | | if (a == b) {
124 | | string memory aStr = FuzzLibString.toString(a);
125 | | string memory bStr = FuzzLibString.toString(b);
126 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "==", reason);
127 | | emit AssertNeqFail(assertMsg);
128 | | platform.assertFail();
129 | | }
130 | | }
131 | |
132 | | /// @notice asserts that a is greater than or equal to b. Violations are logged using reason.
133 | * | function gte(
134 | | uint256 a,
135 | | uint256 b,
136 | | string memory reason
137 | | ) public {
138 | * | if (!(a >= b)) {
139 | | string memory aStr = FuzzLibString.toString(a);
140 | | string memory bStr = FuzzLibString.toString(b);
141 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<", reason);
142 | | emit AssertGteFail(assertMsg);
143 | | platform.assertFail();
144 | | }
145 | | }
146 | |
147 | | /// @notice int256 version of gte
148 | | function gte(
149 | | int256 a,
150 | | int256 b,
151 | | string memory reason
152 | | ) public {
153 | | if (!(a >= b)) {
154 | | string memory aStr = FuzzLibString.toString(a);
155 | | string memory bStr = FuzzLibString.toString(b);
156 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<", reason);
157 | | emit AssertGteFail(assertMsg);
158 | | platform.assertFail();
159 | | }
160 | | }
161 | |
162 | | /// @notice asserts that a is greater than b. Violations are logged using reason.
163 | * | function gt(
164 | | uint256 a,
165 | | uint256 b,
166 | | string memory reason
167 | | ) public {
168 | * | if (!(a > b)) {
169 | | string memory aStr = FuzzLibString.toString(a);
170 | | string memory bStr = FuzzLibString.toString(b);
171 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<=", reason);
172 | | emit AssertGtFail(assertMsg);
173 | | platform.assertFail();
174 | | }
175 | | }
176 | |
177 | | /// @notice int256 version of gt
178 | | function gt(
179 | | int256 a,
180 | | int256 b,
181 | | string memory reason
182 | | ) public {
183 | | if (!(a > b)) {
184 | | string memory aStr = FuzzLibString.toString(a);
185 | | string memory bStr = FuzzLibString.toString(b);
186 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<=", reason);
187 | | emit AssertGtFail(assertMsg);
188 | | platform.assertFail();
189 | | }
190 | | }
191 | |
192 | | /// @notice asserts that a is less than or equal to b. Violations are logged using reason.
193 | * | function lte(
194 | | uint256 a,
195 | | uint256 b,
196 | | string memory reason
197 | | ) public {
198 | * | if (!(a <= b)) {
199 | | string memory aStr = FuzzLibString.toString(a);
200 | | string memory bStr = FuzzLibString.toString(b);
201 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">", reason);
202 | | emit AssertLteFail(assertMsg);
203 | | platform.assertFail();
204 | | }
205 | | }
206 | |
207 | | /// @notice int256 version of lte
208 | | function lte(
209 | | int256 a,
210 | | int256 b,
211 | | string memory reason
212 | | ) public {
213 | | if (!(a <= b)) {
214 | | string memory aStr = FuzzLibString.toString(a);
215 | | string memory bStr = FuzzLibString.toString(b);
216 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">", reason);
217 | | emit AssertLteFail(assertMsg);
218 | | platform.assertFail();
219 | | }
220 | | }
221 | |
222 | | /// @notice asserts that a is less than b. Violations are logged using reason.
223 | * | function lt(
224 | | uint256 a,
225 | | uint256 b,
226 | | string memory reason
227 | | ) public {
228 | * | if (!(a < b)) {
229 | | string memory aStr = FuzzLibString.toString(a);
230 | | string memory bStr = FuzzLibString.toString(b);
231 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">=", reason);
232 | | emit AssertLtFail(assertMsg);
233 | | platform.assertFail();
234 | | }
235 | | }
236 | |
237 | | /// @notice int256 version of lt
238 | | function lt(
239 | | int256 a,
240 | | int256 b,
241 | | string memory reason
242 | | ) public {
243 | | if (!(a < b)) {
244 | | string memory aStr = FuzzLibString.toString(a);
245 | | string memory bStr = FuzzLibString.toString(b);
246 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">=", reason);
247 | | emit AssertLtFail(assertMsg);
248 | | platform.assertFail();
249 | | }
250 | | }
251 | |
252 | | function assertRevertReasonNotEqual(
253 | | bytes memory returnData,
254 | | string memory reason
255 | | ) public {
256 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason);
257 | | t(!isEqual, reason);
258 | | }
259 | |
260 | | function assertRevertReasonEqual(
261 | | bytes memory returnData,
262 | | string memory reason
263 | | ) public {
264 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason);
265 | | t(isEqual, reason);
266 | | }
267 | |
268 | | function assertRevertReasonEqual(
269 | | bytes memory returnData,
270 | | string memory reason1,
271 | | string memory reason2
272 | | ) public {
273 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) ||
274 | | FuzzLibString.isRevertReasonEqual(returnData, reason2);
275 | | string memory assertMsg = string(
276 | | abi.encodePacked(reason1, " OR ", reason2)
277 | | );
278 | | t(isEqual, assertMsg);
279 | | }
280 | |
281 | | function assertRevertReasonEqual(
282 | | bytes memory returnData,
283 | | string memory reason1,
284 | | string memory reason2,
285 | | string memory reason3
286 | | ) public {
287 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) ||
288 | | FuzzLibString.isRevertReasonEqual(returnData, reason2) ||
289 | | FuzzLibString.isRevertReasonEqual(returnData, reason3);
290 | | string memory assertMsg = string(
291 | | abi.encodePacked(reason1, " OR ", reason2, " OR ", reason3)
292 | | );
293 | | t(isEqual, assertMsg);
294 | | }
295 | |
296 | | function assertRevertReasonEqual(
297 | | bytes memory returnData,
298 | | string memory reason1,
299 | | string memory reason2,
300 | | string memory reason3,
301 | | string memory reason4
302 | | ) public {
303 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) ||
304 | | FuzzLibString.isRevertReasonEqual(returnData, reason2) ||
305 | | FuzzLibString.isRevertReasonEqual(returnData, reason3) ||
306 | | FuzzLibString.isRevertReasonEqual(returnData, reason4);
307 | | string memory assertMsg = string(
308 | | abi.encodePacked(
309 | | reason1,
310 | | " OR ",
311 | | reason2,
312 | | " OR ",
313 | | reason3,
314 | | " OR ",
315 | | reason4
316 | | )
317 | | );
318 | | t(isEqual, assertMsg);
319 | | }
320 | |
321 | | function errAllow(
322 | | bytes4 errorSelector,
323 | | bytes4[] memory allowedErrors,
324 | | string memory message
325 | | ) public {
326 | | bool allowed = false;
327 | | for (uint256 i = 0; i < allowedErrors.length; i++) {
328 | | if (errorSelector == allowedErrors[i]) {
329 | | allowed = true;
330 | | break;
331 | | }
332 | | }
333 | | t(allowed, message);
334 | | }
335 | |
336 | | function errsAllow(
337 | | bytes4 errorSelector,
338 | | bytes4[] memory allowedErrors,
339 | | string[] memory messages
340 | | ) public {
341 | | bool allowed = false;
342 | | uint256 passIndex = 0;
343 | | for (uint256 i = 0; i < allowedErrors.length; i++) {
344 | | if (errorSelector == allowedErrors[i]) {
345 | | allowed = true;
346 | | passIndex = i;
347 | | break;
348 | | }
349 | | }
350 | | t(allowed, messages[passIndex]);
351 | | }
352 | |
353 | | function createAssertFailMessage(string memory aStr, string memory bStr, string memory operator, string memory reason)internal pure returns (string memory) {
354 | | return string(abi.encodePacked("Invalid: ", aStr, operator, bStr, ", reason: ", reason));
355 | | }
356 | |
357 | | }
358 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperBase.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {IPlatform} from "../platform/IPlatform.sol";
5 | |
6 | | contract HelperBase {
7 | | IPlatform public platform;
8 | |
9 | | function setPlatform(address _platform) public {
10 | | platform = IPlatform(_platform);
11 | | }
12 | | }
13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperClamp.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "../FuzzLibString.sol";
5 | | import "./HelperAssert.sol";
6 | |
7 | | /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol)
8 | | abstract contract HelperClamp is HelperAssert {
9 | | event Clamped(string);
10 | |
11 | | /*
12 | | **************************************************************************
13 | | * Clamp functions with logging enabled
14 | | **************************************************************************
15 | | */
16 | |
17 | | /// @notice Clamps value to be between low and high, both inclusive
18 | * | function clamp(
19 | | uint256 value,
20 | | uint256 low,
21 | | uint256 high
22 | * | ) public returns (uint256) {
23 | * | return clamp(value, low, high, true);
24 | | }
25 | |
26 | | /// @notice int256 version of clamp
27 | | function clamp(
28 | | int256 value,
29 | | int256 low,
30 | | int256 high
31 | | ) public returns (int256) {
32 | | return clamp(value, low, high, true);
33 | | }
34 | |
35 | | /// @notice clamps a to be less than b
36 | | function clampLt(uint256 a, uint256 b) public returns (uint256) {
37 | | return clampLt(a, b);
38 | | }
39 | |
40 | | /// @notice int256 version of clampLt
41 | | function clampLt(int256 a, int256 b) public returns (int256) {
42 | | return clampLt(a, b, true);
43 | | }
44 | |
45 | | /// @notice clamps a to be less than or equal to b
46 | | function clampLte(uint256 a, uint256 b) public returns (uint256) {
47 | | return clampLte(a, b, true);
48 | | }
49 | |
50 | | /// @notice int256 version of clampLte
51 | | function clampLte(int256 a, int256 b) public returns (int256) {
52 | | return clampLte(a, b, true);
53 | | }
54 | |
55 | | /// @notice clamps a to be greater than b
56 | | function clampGt(uint256 a, uint256 b) public returns (uint256) {
57 | | return clampGt(a, b, true);
58 | | }
59 | |
60 | | /// @notice int256 version of clampGt
61 | | function clampGt(int256 a, int256 b) public returns (int256) {
62 | | return clampGt(a, b, true);
63 | | }
64 | |
65 | | /// @notice clamps a to be greater than or equal to b
66 | | function clampGte(uint256 a, uint256 b) public returns (uint256) {
67 | | return clampGte(a, b, true);
68 | | }
69 | |
70 | | /// @notice int256 version of clampGte
71 | | function clampGte(int256 a, int256 b) public returns (int256) {
72 | | return clampGte(a, b, true);
73 | | }
74 | |
75 | | /*
76 | | **************************************************************************
77 | | * Clamp functions with optional logging
78 | | **************************************************************************
79 | | */
80 | |
81 | | /// @notice Clamps value to be between low and high, both inclusive
82 | * | function clamp(
83 | | uint256 value,
84 | | uint256 low,
85 | | uint256 high,
86 | | bool enableLogs
87 | * | ) public returns (uint256) {
88 | * | if (value < low || value > high) {
89 | * | uint256 ans = low + (value % (high - low + 1));
90 | * | if (enableLogs) {
91 | * | string memory valueStr = FuzzLibString.toString(value);
92 | * | string memory ansStr = FuzzLibString.toString(ans);
93 | * | bytes memory message = abi.encodePacked(
94 | | "Clamping value ",
95 | * | valueStr,
96 | | " to ",
97 | * | ansStr
98 | | );
99 | * | emit Clamped(string(message));
100 | | }
101 | * | return ans;
102 | | }
103 | * | return value;
104 | | }
105 | |
106 | | /// @notice int256 version of clamp
107 | | function clamp(
108 | | int256 value,
109 | | int256 low,
110 | | int256 high,
111 | | bool enableLogs
112 | | ) public returns (int256) {
113 | | if (value < low || value > high) {
114 | | int256 range = high - low + 1;
115 | | int256 clamped = (value - low) % (range);
116 | | if (clamped < 0) clamped += range;
117 | | int256 ans = low + clamped;
118 | | if (enableLogs) {
119 | | string memory valueStr = FuzzLibString.toString(value);
120 | | string memory ansStr = FuzzLibString.toString(ans);
121 | | bytes memory message = abi.encodePacked(
122 | | "Clamping value ",
123 | | valueStr,
124 | | " to ",
125 | | ansStr
126 | | );
127 | | emit Clamped(string(message));
128 | | }
129 | | return ans;
130 | | }
131 | | return value;
132 | | }
133 | |
134 | | /// @notice clamps a to be less than b
135 | | function clampLt(
136 | | uint256 a,
137 | | uint256 b,
138 | | bool enableLogs
139 | | ) public returns (uint256) {
140 | | if (!(a < b)) {
141 | | neq(
142 | | b,
143 | | 0,
144 | | "clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions."
145 | | );
146 | | uint256 value = a % b;
147 | | if (enableLogs) {
148 | | string memory aStr = FuzzLibString.toString(a);
149 | | string memory valueStr = FuzzLibString.toString(value);
150 | | bytes memory message = abi.encodePacked(
151 | | "Clamping value ",
152 | | aStr,
153 | | " to ",
154 | | valueStr
155 | | );
156 | | emit Clamped(string(message));
157 | | }
158 | | return value;
159 | | }
160 | | return a;
161 | | }
162 | |
163 | | /// @notice int256 version of clampLt
164 | | function clampLt(
165 | | int256 a,
166 | | int256 b,
167 | | bool enableLogs
168 | | ) public returns (int256) {
169 | | if (!(a < b)) {
170 | | int256 value = b - 1;
171 | | if (enableLogs) {
172 | | string memory aStr = FuzzLibString.toString(a);
173 | | string memory valueStr = FuzzLibString.toString(value);
174 | | bytes memory message = abi.encodePacked(
175 | | "Clamping value ",
176 | | aStr,
177 | | " to ",
178 | | valueStr
179 | | );
180 | | emit Clamped(string(message));
181 | | }
182 | | return value;
183 | | }
184 | | return a;
185 | | }
186 | |
187 | | /// @notice clamps a to be less than or equal to b
188 | | function clampLte(
189 | | uint256 a,
190 | | uint256 b,
191 | | bool enableLogs
192 | | ) public returns (uint256) {
193 | | if (!(a <= b)) {
194 | | uint256 value = a % (b + 1);
195 | | if (enableLogs) {
196 | | string memory aStr = FuzzLibString.toString(a);
197 | | string memory valueStr = FuzzLibString.toString(value);
198 | | bytes memory message = abi.encodePacked(
199 | | "Clamping value ",
200 | | aStr,
201 | | " to ",
202 | | valueStr
203 | | );
204 | | emit Clamped(string(message));
205 | | }
206 | | return value;
207 | | }
208 | | return a;
209 | | }
210 | |
211 | | /// @notice int256 version of clampLte
212 | | function clampLte(
213 | | int256 a,
214 | | int256 b,
215 | | bool enableLogs
216 | | ) public returns (int256) {
217 | | if (!(a <= b)) {
218 | | int256 value = b;
219 | | if (enableLogs) {
220 | | string memory aStr = FuzzLibString.toString(a);
221 | | string memory valueStr = FuzzLibString.toString(value);
222 | | bytes memory message = abi.encodePacked(
223 | | "Clamping value ",
224 | | aStr,
225 | | " to ",
226 | | valueStr
227 | | );
228 | | emit Clamped(string(message));
229 | | }
230 | | return value;
231 | | }
232 | | return a;
233 | | }
234 | |
235 | | /// @notice clamps a to be greater than b
236 | | function clampGt(
237 | | uint256 a,
238 | | uint256 b,
239 | | bool enableLogs
240 | | ) public returns (uint256) {
241 | | if (!(a > b)) {
242 | | neq(
243 | | b,
244 | | type(uint256).max,
245 | | "clampGt cannot clamp value a to be larger than uint256.max. Check your inputs/assumptions."
246 | | );
247 | | uint256 value = b + 1;
248 | | if (enableLogs) {
249 | | string memory aStr = FuzzLibString.toString(a);
250 | | string memory valueStr = FuzzLibString.toString(value);
251 | | bytes memory message = abi.encodePacked(
252 | | "Clamping value ",
253 | | aStr,
254 | | " to ",
255 | | valueStr
256 | | );
257 | | emit Clamped(string(message));
258 | | }
259 | | return value;
260 | | } else {
261 | | return a;
262 | | }
263 | | }
264 | |
265 | | /// @notice int256 version of clampGt
266 | | function clampGt(
267 | | int256 a,
268 | | int256 b,
269 | | bool enableLogs
270 | | ) public returns (int256) {
271 | | if (!(a > b)) {
272 | | int256 value = b + 1;
273 | | if (enableLogs) {
274 | | string memory aStr = FuzzLibString.toString(a);
275 | | string memory valueStr = FuzzLibString.toString(value);
276 | | bytes memory message = abi.encodePacked(
277 | | "Clamping value ",
278 | | aStr,
279 | | " to ",
280 | | valueStr
281 | | );
282 | | emit Clamped(string(message));
283 | | }
284 | | return value;
285 | | } else {
286 | | return a;
287 | | }
288 | | }
289 | |
290 | | /// @notice clamps a to be greater than or equal to b
291 | | function clampGte(
292 | | uint256 a,
293 | | uint256 b,
294 | | bool enableLogs
295 | | ) public returns (uint256) {
296 | | if (!(a > b)) {
297 | | uint256 value = b;
298 | | if (enableLogs) {
299 | | string memory aStr = FuzzLibString.toString(a);
300 | | string memory valueStr = FuzzLibString.toString(value);
301 | | bytes memory message = abi.encodePacked(
302 | | "Clamping value ",
303 | | aStr,
304 | | " to ",
305 | | valueStr
306 | | );
307 | | emit Clamped(string(message));
308 | | }
309 | | return value;
310 | | }
311 | | return a;
312 | | }
313 | |
314 | | /// @notice int256 version of clampGte
315 | | function clampGte(
316 | | int256 a,
317 | | int256 b,
318 | | bool enableLogs
319 | | ) public returns (int256) {
320 | | if (!(a > b)) {
321 | | int256 value = b;
322 | | if (enableLogs) {
323 | | string memory aStr = FuzzLibString.toString(a);
324 | | string memory valueStr = FuzzLibString.toString(value);
325 | | bytes memory message = abi.encodePacked(
326 | | "Clamping value ",
327 | | aStr,
328 | | " to ",
329 | | valueStr
330 | | );
331 | | emit Clamped(string(message));
332 | | }
333 | | return value;
334 | | }
335 | | return a;
336 | | }
337 | | }
338 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperLog.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {LibLog} from "../libraries/LibLog.sol";
5 | |
6 | | abstract contract HelperLog {
7 | * | function log(string memory message) public {
8 | * | LibLog.log(message);
9 | | }
10 | |
11 | | function log(string memory message, string memory data) public {
12 | | LibLog.log(message, data);
13 | | }
14 | |
15 | | function log(string memory message, bytes memory data) public {
16 | | LibLog.log(message, data);
17 | | }
18 | |
19 | * | function log(string memory message, uint256 data) public {
20 | * | LibLog.log(message, data);
21 | | }
22 | |
23 | | function log(string memory message, int256 data) public {
24 | | LibLog.log(message, data);
25 | | }
26 | |
27 | | function log(string memory message, address data) public {
28 | | LibLog.log(message, data);
29 | | }
30 | |
31 | | function log(string memory message, bool data) public {
32 | | LibLog.log(message, data);
33 | | }
34 | |
35 | | function log(string memory message, bytes32 data) public {
36 | | LibLog.log(message, data);
37 | | }
38 | |
39 | | function logFail() public {
40 | | LibLog.logFail();
41 | | }
42 | |
43 | | function logFail(string memory message) public {
44 | | LibLog.logFail(message);
45 | | }
46 | |
47 | | function logFail(string memory message, string memory data) public {
48 | | LibLog.logFail(message, data);
49 | | }
50 | |
51 | | function logFail(string memory message, bytes memory data) public {
52 | | LibLog.logFail(message, data);
53 | | }
54 | |
55 | | function logFail(string memory message, uint256 data) public {
56 | | LibLog.logFail(message, data);
57 | | }
58 | |
59 | | function logFail(string memory message, int256 data) public {
60 | | LibLog.logFail(message, data);
61 | | }
62 | |
63 | | function logFail(string memory message, address data) public {
64 | | LibLog.logFail(message, data);
65 | | }
66 | |
67 | | function logFail(string memory message, bool data) public {
68 | | LibLog.logFail(message, data);
69 | | }
70 | |
71 | | function logFail(string memory message, bytes32 data) public {
72 | | LibLog.log(message, data);
73 | | }
74 | | }
75 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperMath.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | abstract contract HelperMath {
5 | | function min(uint256 a, uint256 b) public pure returns (uint256) {
6 | | return a < b ? a : b;
7 | | }
8 | |
9 | | function max(uint256 a, uint256 b) public pure returns (uint256) {
10 | | return a > b ? a : b;
11 | | }
12 | |
13 | | // Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/utils/math/SignedMath.sol
14 | | function max(int256 a, int256 b) public pure returns (int256) {
15 | | return a > b ? a : b;
16 | | }
17 | |
18 | | // Forked with modifications from https://ethereum.stackexchange.com/a/84391
19 | | function abs(int128 n) public pure returns (int128) {
20 | | return n >= 0 ? n : -n;
21 | | }
22 | |
23 | | function abs(int256 n) public pure returns (uint256) {
24 | | return n >= 0 ? uint256(n) : uint256(-n);
25 | | }
26 | |
27 | | function diff(int256 a, int256 b) public pure returns (uint256) {
28 | | return a >= b ? uint256(a - b) : uint256(b - a);
29 | | }
30 | |
31 | | function diff(uint256 a, uint256 b) public pure returns (uint256) {
32 | | return a >= b ? a - b : b - a;
33 | | }
34 | | }
35 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperRandom.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | abstract contract HelperRandom {
5 | | /// @notice Shuffle an array using Fisher-Yates algorithm
6 | | /// @dev Based on https://gist.github.com/scammi/602387a22e04c77beb73c0ebc0f0bc18
7 | | function shuffleArray(
8 | | uint256[] memory shuffle,
9 | | uint256 entropy
10 | | ) public pure {
11 | | for (uint256 i = shuffle.length - 1; i > 0; i--) {
12 | | uint256 swapIndex = entropy % (shuffle.length - i);
13 | |
14 | | uint256 currentIndex = shuffle[i];
15 | | uint256 indexToSwap = shuffle[swapIndex];
16 | |
17 | | shuffle[i] = indexToSwap;
18 | | shuffle[swapIndex] = currentIndex;
19 | | }
20 | | }
21 | | }
22 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/libraries/LibLog.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | * | library LibLog {
5 | | event Log(string message);
6 | | event LogString(string message, string data);
7 | | event LogBytes(string message, bytes data);
8 | | event LogUint(string message, uint256 data);
9 | | event LogInt(string message, int256 data);
10 | | event LogAddress(string message, address data);
11 | | event LogBool(string message, bool data);
12 | | event LogBytes32(string message, bytes32 data);
13 | |
14 | | event AssertionFailed();
15 | | event AssertionFailed(string message);
16 | | event AssertionFailed(string message, string data);
17 | | event AssertionFailed(string message, bytes data);
18 | | event AssertionFailed(string message, uint256 data);
19 | | event AssertionFailed(string message, int256 data);
20 | | event AssertionFailed(string message, address data);
21 | | event AssertionFailed(string message, bool data);
22 | |
23 | * | function log(string memory message) internal {
24 | * | emit Log(message);
25 | | }
26 | |
27 | | function log(string memory message, string memory data) internal {
28 | | emit LogString(message, data);
29 | | }
30 | |
31 | | function log(string memory message, bytes memory data) internal {
32 | | emit LogBytes(message, data);
33 | | }
34 | |
35 | * | function log(string memory message, uint256 data) internal {
36 | * | emit LogUint(message, data);
37 | | }
38 | |
39 | | function log(string memory message, int256 data) internal {
40 | | emit LogInt(message, data);
41 | | }
42 | |
43 | | function log(string memory message, address data) internal {
44 | | emit LogAddress(message, data);
45 | | }
46 | |
47 | | function log(string memory message, bool data) internal {
48 | | emit LogBool(message, data);
49 | | }
50 | |
51 | | function log(string memory message, bytes32 data) internal {
52 | | emit LogBytes32(message, data);
53 | | }
54 | |
55 | | function logFail() internal {
56 | | emit AssertionFailed();
57 | | }
58 | |
59 | | function logFail(string memory message) internal {
60 | | emit AssertionFailed(message);
61 | | }
62 | |
63 | | function logFail(string memory message, string memory data) internal {
64 | | emit AssertionFailed(message, data);
65 | | }
66 | |
67 | | function logFail(string memory message, bytes memory data) internal {
68 | | emit AssertionFailed(message, data);
69 | | }
70 | |
71 | | function logFail(string memory message, uint256 data) internal {
72 | | emit AssertionFailed(message, data);
73 | | }
74 | |
75 | | function logFail(string memory message, int256 data) internal {
76 | | emit AssertionFailed(message, data);
77 | | }
78 | |
79 | | function logFail(string memory message, address data) internal {
80 | | emit AssertionFailed(message, data);
81 | | }
82 | |
83 | | function logFail(string memory message, bool data) internal {
84 | | emit AssertionFailed(message, data);
85 | | }
86 | |
87 | | function logFail(string memory message, bytes32 data) internal {
88 | | emit LogBytes32(message, data);
89 | | }
90 | | }
91 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/platform/IPlatform.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | interface IPlatform {
5 | | function assertFail() pure external;
6 | | }
7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/platform/PlatformCrytic.sol
1 | |
2 | | // SPDX-License-Identifier: MIT
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import {IPlatform} from "./IPlatform.sol";
6 | |
7 | * | contract PlatformCrytic is IPlatform {
8 | * | function assertFail() pure public override{
9 | * | assert(false);
10 | | }
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | // solhint-disable-next-line interface-starts-with-i
5 | | interface AggregatorInterface {
6 | | function latestAnswer() external view returns (int256);
7 | |
8 | | function latestTimestamp() external view returns (uint256);
9 | |
10 | | function latestRound() external view returns (uint256);
11 | |
12 | | function getAnswer(uint256 roundId) external view returns (int256);
13 | |
14 | | function getTimestamp(uint256 roundId) external view returns (uint256);
15 | |
16 | | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
17 | |
18 | | event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
19 | | }
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import {AggregatorInterface} from "./AggregatorInterface.sol";
5 | | import {AggregatorV3Interface} from "./AggregatorV3Interface.sol";
6 | |
7 | | // solhint-disable-next-line interface-starts-with-i
8 | | interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}
9 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | // solhint-disable-next-line interface-starts-with-i
5 | | interface AggregatorV3Interface {
6 | | function decimals() external view returns (uint8);
7 | |
8 | | function description() external view returns (string memory);
9 | |
10 | | function version() external view returns (uint256);
11 | |
12 | | function getRoundData(
13 | | uint80 _roundId
14 | | ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
15 | |
16 | | function latestRoundData()
17 | | external
18 | | view
19 | | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
20 | | }
21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./OwnableUpgradeable.sol";
7 | | import "../proxy/utils/Initializable.sol";
8 | |
9 | | /**
10 | | * @dev Contract module which provides access control mechanism, where
11 | | * there is an account (an owner) that can be granted exclusive access to
12 | | * specific functions.
13 | | *
14 | | * By default, the owner account will be the one that deploys the contract. This
15 | | * can later be changed with {transferOwnership} and {acceptOwnership}.
16 | | *
17 | | * This module is used through inheritance. It will make available all functions
18 | | * from parent (Ownable).
19 | | */
20 | | abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
21 | | function __Ownable2Step_init() internal onlyInitializing {
22 | | __Ownable_init_unchained();
23 | | }
24 | |
25 | | function __Ownable2Step_init_unchained() internal onlyInitializing {
26 | | }
27 | | address private _pendingOwner;
28 | |
29 | | event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
30 | |
31 | | /**
32 | | * @dev Returns the address of the pending owner.
33 | | */
34 | | function pendingOwner() public view virtual returns (address) {
35 | | return _pendingOwner;
36 | | }
37 | |
38 | | /**
39 | | * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
40 | | * Can only be called by the current owner.
41 | | */
42 | | function transferOwnership(address newOwner) public virtual override onlyOwner {
43 | | _pendingOwner = newOwner;
44 | | emit OwnershipTransferStarted(owner(), newOwner);
45 | | }
46 | |
47 | | /**
48 | | * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
49 | | * Internal function without access restriction.
50 | | */
51 | | function _transferOwnership(address newOwner) internal virtual override {
52 | | delete _pendingOwner;
53 | | super._transferOwnership(newOwner);
54 | | }
55 | |
56 | | /**
57 | | * @dev The new owner accepts the ownership transfer.
58 | | */
59 | | function acceptOwnership() external {
60 | | address sender = _msgSender();
61 | | require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
62 | | _transferOwnership(sender);
63 | | }
64 | |
65 | | /**
66 | | * @dev This empty reserved space is put in place to allow future versions to add new
67 | | * variables without shifting down storage in the inheritance chain.
68 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
69 | | */
70 | | uint256[49] private __gap;
71 | | }
72 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../utils/ContextUpgradeable.sol";
7 | | import "../proxy/utils/Initializable.sol";
8 | |
9 | | /**
10 | | * @dev Contract module which provides a basic access control mechanism, where
11 | | * there is an account (an owner) that can be granted exclusive access to
12 | | * specific functions.
13 | | *
14 | | * By default, the owner account will be the one that deploys the contract. This
15 | | * can later be changed with {transferOwnership}.
16 | | *
17 | | * This module is used through inheritance. It will make available the modifier
18 | | * `onlyOwner`, which can be applied to your functions to restrict their use to
19 | | * the owner.
20 | | */
21 | | abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
22 | | address private _owner;
23 | |
24 | | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
25 | |
26 | | /**
27 | | * @dev Initializes the contract setting the deployer as the initial owner.
28 | | */
29 | | function __Ownable_init() internal onlyInitializing {
30 | | __Ownable_init_unchained();
31 | | }
32 | |
33 | | function __Ownable_init_unchained() internal onlyInitializing {
34 | | _transferOwnership(_msgSender());
35 | | }
36 | |
37 | | /**
38 | | * @dev Throws if called by any account other than the owner.
39 | | */
40 | | modifier onlyOwner() {
41 | | _checkOwner();
42 | | _;
43 | | }
44 | |
45 | | /**
46 | | * @dev Returns the address of the current owner.
47 | | */
48 | | function owner() public view virtual returns (address) {
49 | | return _owner;
50 | | }
51 | |
52 | | /**
53 | | * @dev Throws if the sender is not the owner.
54 | | */
55 | | function _checkOwner() internal view virtual {
56 | | require(owner() == _msgSender(), "Ownable: caller is not the owner");
57 | | }
58 | |
59 | | /**
60 | | * @dev Leaves the contract without owner. It will not be possible to call
61 | | * `onlyOwner` functions anymore. Can only be called by the current owner.
62 | | *
63 | | * NOTE: Renouncing ownership will leave the contract without an owner,
64 | | * thereby removing any functionality that is only available to the owner.
65 | | */
66 | | function renounceOwnership() public virtual onlyOwner {
67 | | _transferOwnership(address(0));
68 | | }
69 | |
70 | | /**
71 | | * @dev Transfers ownership of the contract to a new account (`newOwner`).
72 | | * Can only be called by the current owner.
73 | | */
74 | | function transferOwnership(address newOwner) public virtual onlyOwner {
75 | | require(newOwner != address(0), "Ownable: new owner is the zero address");
76 | | _transferOwnership(newOwner);
77 | | }
78 | |
79 | | /**
80 | | * @dev Transfers ownership of the contract to a new account (`newOwner`).
81 | | * Internal function without access restriction.
82 | | */
83 | | function _transferOwnership(address newOwner) internal virtual {
84 | | address oldOwner = _owner;
85 | | _owner = newOwner;
86 | | emit OwnershipTransferred(oldOwner, newOwner);
87 | | }
88 | |
89 | | /**
90 | | * @dev This empty reserved space is put in place to allow future versions to add new
91 | | * variables without shifting down storage in the inheritance chain.
92 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
93 | | */
94 | | uint256[49] private __gap;
95 | | }
96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)
3 | |
4 | | pragma solidity ^0.8.2;
5 | |
6 | | import "../../utils/AddressUpgradeable.sol";
7 | |
8 | | /**
9 | | * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
10 | | * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
11 | | * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
12 | | * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
13 | | *
14 | | * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
15 | | * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
16 | | * case an upgrade adds a module that needs to be initialized.
17 | | *
18 | | * For example:
19 | | *
20 | | * [.hljs-theme-light.nopadding]
21 | | * ```
22 | | * contract MyToken is ERC20Upgradeable {
23 | | * function initialize() initializer public {
24 | | * __ERC20_init("MyToken", "MTK");
25 | | * }
26 | | * }
27 | | * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
28 | | * function initializeV2() reinitializer(2) public {
29 | | * __ERC20Permit_init("MyToken");
30 | | * }
31 | | * }
32 | | * ```
33 | | *
34 | | * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
35 | | * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
36 | | *
37 | | * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
38 | | * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
39 | | *
40 | | * [CAUTION]
41 | | * ====
42 | | * Avoid leaving a contract uninitialized.
43 | | *
44 | | * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
45 | | * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
46 | | * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
47 | | *
48 | | * [.hljs-theme-light.nopadding]
49 | | * ```
50 | | * /// @custom:oz-upgrades-unsafe-allow constructor
51 | | * constructor() {
52 | | * _disableInitializers();
53 | | * }
54 | | * ```
55 | | * ====
56 | | */
57 | | abstract contract Initializable {
58 | | /**
59 | | * @dev Indicates that the contract has been initialized.
60 | | * @custom:oz-retyped-from bool
61 | | */
62 | | uint8 private _initialized;
63 | |
64 | | /**
65 | | * @dev Indicates that the contract is in the process of being initialized.
66 | | */
67 | | bool private _initializing;
68 | |
69 | | /**
70 | | * @dev Triggered when the contract has been initialized or reinitialized.
71 | | */
72 | | event Initialized(uint8 version);
73 | |
74 | | /**
75 | | * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
76 | | * `onlyInitializing` functions can be used to initialize parent contracts.
77 | | *
78 | | * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
79 | | * constructor.
80 | | *
81 | | * Emits an {Initialized} event.
82 | | */
83 | | modifier initializer() {
84 | | bool isTopLevelCall = !_initializing;
85 | | require(
86 | | (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
87 | | "Initializable: contract is already initialized"
88 | | );
89 | | _initialized = 1;
90 | | if (isTopLevelCall) {
91 | | _initializing = true;
92 | | }
93 | | _;
94 | | if (isTopLevelCall) {
95 | | _initializing = false;
96 | | emit Initialized(1);
97 | | }
98 | | }
99 | |
100 | | /**
101 | | * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
102 | | * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
103 | | * used to initialize parent contracts.
104 | | *
105 | | * A reinitializer may be used after the original initialization step. This is essential to configure modules that
106 | | * are added through upgrades and that require initialization.
107 | | *
108 | | * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
109 | | * cannot be nested. If one is invoked in the context of another, execution will revert.
110 | | *
111 | | * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
112 | | * a contract, executing them in the right order is up to the developer or operator.
113 | | *
114 | | * WARNING: setting the version to 255 will prevent any future reinitialization.
115 | | *
116 | | * Emits an {Initialized} event.
117 | | */
118 | | modifier reinitializer(uint8 version) {
119 | | require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
120 | | _initialized = version;
121 | | _initializing = true;
122 | | _;
123 | | _initializing = false;
124 | | emit Initialized(version);
125 | | }
126 | |
127 | | /**
128 | | * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
129 | | * {initializer} and {reinitializer} modifiers, directly or indirectly.
130 | | */
131 | | modifier onlyInitializing() {
132 | | require(_initializing, "Initializable: contract is not initializing");
133 | | _;
134 | | }
135 | |
136 | | /**
137 | | * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
138 | | * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
139 | | * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
140 | | * through proxies.
141 | | *
142 | | * Emits an {Initialized} event the first time it is successfully executed.
143 | | */
144 | | function _disableInitializers() internal virtual {
145 | | require(!_initializing, "Initializable: contract is initializing");
146 | | if (_initialized < type(uint8).max) {
147 | | _initialized = type(uint8).max;
148 | | emit Initialized(type(uint8).max);
149 | | }
150 | | }
151 | |
152 | | /**
153 | | * @dev Returns the highest version that has been initialized. See {reinitializer}.
154 | | */
155 | | function _getInitializedVersion() internal view returns (uint8) {
156 | | return _initialized;
157 | | }
158 | |
159 | | /**
160 | | * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
161 | | */
162 | | function _isInitializing() internal view returns (bool) {
163 | | return _initializing;
164 | | }
165 | | }
166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | | import "../proxy/utils/Initializable.sol";
6 | |
7 | | /**
8 | | * @dev Contract module that helps prevent reentrant calls to a function.
9 | | *
10 | | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
11 | | * available, which can be applied to functions to make sure there are no nested
12 | | * (reentrant) calls to them.
13 | | *
14 | | * Note that because there is a single `nonReentrant` guard, functions marked as
15 | | * `nonReentrant` may not call one another. This can be worked around by making
16 | | * those functions `private`, and then adding `external` `nonReentrant` entry
17 | | * points to them.
18 | | *
19 | | * TIP: If you would like to learn more about reentrancy and alternative ways
20 | | * to protect against it, check out our blog post
21 | | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
22 | | */
23 | | abstract contract ReentrancyGuardUpgradeable is Initializable {
24 | | // Booleans are more expensive than uint256 or any type that takes up a full
25 | | // word because each write operation emits an extra SLOAD to first read the
26 | | // slot's contents, replace the bits taken up by the boolean, and then write
27 | | // back. This is the compiler's defense against contract upgrades and
28 | | // pointer aliasing, and it cannot be disabled.
29 | |
30 | | // The values being non-zero value makes deployment a bit more expensive,
31 | | // but in exchange the refund on every call to nonReentrant will be lower in
32 | | // amount. Since refunds are capped to a percentage of the total
33 | | // transaction's gas, it is best to keep them low in cases like this one, to
34 | | // increase the likelihood of the full refund coming into effect.
35 | * | uint256 private constant _NOT_ENTERED = 1;
36 | * | uint256 private constant _ENTERED = 2;
37 | |
38 | | uint256 private _status;
39 | |
40 | | function __ReentrancyGuard_init() internal onlyInitializing {
41 | | __ReentrancyGuard_init_unchained();
42 | | }
43 | |
44 | | function __ReentrancyGuard_init_unchained() internal onlyInitializing {
45 | | _status = _NOT_ENTERED;
46 | | }
47 | |
48 | | /**
49 | | * @dev Prevents a contract from calling itself, directly or indirectly.
50 | | * Calling a `nonReentrant` function from another `nonReentrant`
51 | | * function is not supported. It is possible to prevent this from happening
52 | | * by making the `nonReentrant` function external, and making it call a
53 | | * `private` function that does the actual work.
54 | | */
55 | | modifier nonReentrant() {
56 | * | _nonReentrantBefore();
57 | * | _;
58 | * | _nonReentrantAfter();
59 | | }
60 | |
61 | * | function _nonReentrantBefore() private {
62 | | // On the first call to nonReentrant, _status will be _NOT_ENTERED
63 | * | require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
64 | |
65 | | // Any calls to nonReentrant after this point will fail
66 | * | _status = _ENTERED;
67 | | }
68 | |
69 | * | function _nonReentrantAfter() private {
70 | | // By storing the original value once again, a refund is triggered (see
71 | | // https://eips.ethereum.org/EIPS/eip-2200)
72 | * | _status = _NOT_ENTERED;
73 | | }
74 | |
75 | | /**
76 | | * @dev This empty reserved space is put in place to allow future versions to add new
77 | | * variables without shifting down storage in the inheritance chain.
78 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
79 | | */
80 | | uint256[49] private __gap;
81 | | }
82 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
3 | |
4 | | pragma solidity ^0.8.1;
5 | |
6 | | /**
7 | | * @dev Collection of functions related to the address type
8 | | */
9 | * | library AddressUpgradeable {
10 | | /**
11 | | * @dev Returns true if `account` is a contract.
12 | | *
13 | | * [IMPORTANT]
14 | | * ====
15 | | * It is unsafe to assume that an address for which this function returns
16 | | * false is an externally-owned account (EOA) and not a contract.
17 | | *
18 | | * Among others, `isContract` will return false for the following
19 | | * types of addresses:
20 | | *
21 | | * - an externally-owned account
22 | | * - a contract in construction
23 | | * - an address where a contract will be created
24 | | * - an address where a contract lived, but was destroyed
25 | | * ====
26 | | *
27 | | * [IMPORTANT]
28 | | * ====
29 | | * You shouldn't rely on `isContract` to protect against flash loan attacks!
30 | | *
31 | | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
32 | | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
33 | | * constructor.
34 | | * ====
35 | | */
36 | | function isContract(address account) internal view returns (bool) {
37 | | // This method relies on extcodesize/address.code.length, which returns 0
38 | | // for contracts in construction, since the code is only stored at the end
39 | | // of the constructor execution.
40 | |
41 | | return account.code.length > 0;
42 | | }
43 | |
44 | | /**
45 | | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
46 | | * `recipient`, forwarding all available gas and reverting on errors.
47 | | *
48 | | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
49 | | * of certain opcodes, possibly making contracts go over the 2300 gas limit
50 | | * imposed by `transfer`, making them unable to receive funds via
51 | | * `transfer`. {sendValue} removes this limitation.
52 | | *
53 | | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
54 | | *
55 | | * IMPORTANT: because control is transferred to `recipient`, care must be
56 | | * taken to not create reentrancy vulnerabilities. Consider using
57 | | * {ReentrancyGuard} or the
58 | | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
59 | | */
60 | | function sendValue(address payable recipient, uint256 amount) internal {
61 | | require(address(this).balance >= amount, "Address: insufficient balance");
62 | |
63 | | (bool success, ) = recipient.call{value: amount}("");
64 | | require(success, "Address: unable to send value, recipient may have reverted");
65 | | }
66 | |
67 | | /**
68 | | * @dev Performs a Solidity function call using a low level `call`. A
69 | | * plain `call` is an unsafe replacement for a function call: use this
70 | | * function instead.
71 | | *
72 | | * If `target` reverts with a revert reason, it is bubbled up by this
73 | | * function (like regular Solidity function calls).
74 | | *
75 | | * Returns the raw returned data. To convert to the expected return value,
76 | | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
77 | | *
78 | | * Requirements:
79 | | *
80 | | * - `target` must be a contract.
81 | | * - calling `target` with `data` must not revert.
82 | | *
83 | | * _Available since v3.1._
84 | | */
85 | | function functionCall(address target, bytes memory data) internal returns (bytes memory) {
86 | | return functionCallWithValue(target, data, 0, "Address: low-level call failed");
87 | | }
88 | |
89 | | /**
90 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
91 | | * `errorMessage` as a fallback revert reason when `target` reverts.
92 | | *
93 | | * _Available since v3.1._
94 | | */
95 | | function functionCall(
96 | | address target,
97 | | bytes memory data,
98 | | string memory errorMessage
99 | | ) internal returns (bytes memory) {
100 | | return functionCallWithValue(target, data, 0, errorMessage);
101 | | }
102 | |
103 | | /**
104 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
105 | | * but also transferring `value` wei to `target`.
106 | | *
107 | | * Requirements:
108 | | *
109 | | * - the calling contract must have an ETH balance of at least `value`.
110 | | * - the called Solidity function must be `payable`.
111 | | *
112 | | * _Available since v3.1._
113 | | */
114 | | function functionCallWithValue(
115 | | address target,
116 | | bytes memory data,
117 | | uint256 value
118 | | ) internal returns (bytes memory) {
119 | | return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
120 | | }
121 | |
122 | | /**
123 | | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
124 | | * with `errorMessage` as a fallback revert reason when `target` reverts.
125 | | *
126 | | * _Available since v3.1._
127 | | */
128 | | function functionCallWithValue(
129 | | address target,
130 | | bytes memory data,
131 | | uint256 value,
132 | | string memory errorMessage
133 | | ) internal returns (bytes memory) {
134 | | require(address(this).balance >= value, "Address: insufficient balance for call");
135 | | (bool success, bytes memory returndata) = target.call{value: value}(data);
136 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage);
137 | | }
138 | |
139 | | /**
140 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
141 | | * but performing a static call.
142 | | *
143 | | * _Available since v3.3._
144 | | */
145 | | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
146 | | return functionStaticCall(target, data, "Address: low-level static call failed");
147 | | }
148 | |
149 | | /**
150 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
151 | | * but performing a static call.
152 | | *
153 | | * _Available since v3.3._
154 | | */
155 | | function functionStaticCall(
156 | | address target,
157 | | bytes memory data,
158 | | string memory errorMessage
159 | | ) internal view returns (bytes memory) {
160 | | (bool success, bytes memory returndata) = target.staticcall(data);
161 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage);
162 | | }
163 | |
164 | | /**
165 | | * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
166 | | * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
167 | | *
168 | | * _Available since v4.8._
169 | | */
170 | | function verifyCallResultFromTarget(
171 | | address target,
172 | | bool success,
173 | | bytes memory returndata,
174 | | string memory errorMessage
175 | | ) internal view returns (bytes memory) {
176 | | if (success) {
177 | | if (returndata.length == 0) {
178 | | // only check isContract if the call was successful and the return data is empty
179 | | // otherwise we already know that it was a contract
180 | | require(isContract(target), "Address: call to non-contract");
181 | | }
182 | | return returndata;
183 | | } else {
184 | | _revert(returndata, errorMessage);
185 | | }
186 | | }
187 | |
188 | | /**
189 | | * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
190 | | * revert reason or using the provided one.
191 | | *
192 | | * _Available since v4.3._
193 | | */
194 | | function verifyCallResult(
195 | | bool success,
196 | | bytes memory returndata,
197 | | string memory errorMessage
198 | | ) internal pure returns (bytes memory) {
199 | | if (success) {
200 | | return returndata;
201 | | } else {
202 | | _revert(returndata, errorMessage);
203 | | }
204 | | }
205 | |
206 | | function _revert(bytes memory returndata, string memory errorMessage) private pure {
207 | | // Look for revert reason and bubble it up if present
208 | | if (returndata.length > 0) {
209 | | // The easiest way to bubble the revert reason is using memory via assembly
210 | | /// @solidity memory-safe-assembly
211 | | assembly {
212 | | let returndata_size := mload(returndata)
213 | | revert(add(32, returndata), returndata_size)
214 | | }
215 | | } else {
216 | | revert(errorMessage);
217 | | }
218 | | }
219 | | }
220 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | | import "../proxy/utils/Initializable.sol";
6 | |
7 | | /**
8 | | * @dev Provides information about the current execution context, including the
9 | | * sender of the transaction and its data. While these are generally available
10 | | * via msg.sender and msg.data, they should not be accessed in such a direct
11 | | * manner, since when dealing with meta-transactions the account sending and
12 | | * paying for execution may not be the actual sender (as far as an application
13 | | * is concerned).
14 | | *
15 | | * This contract is only required for intermediate, library-like contracts.
16 | | */
17 | | abstract contract ContextUpgradeable is Initializable {
18 | | function __Context_init() internal onlyInitializing {
19 | | }
20 | |
21 | | function __Context_init_unchained() internal onlyInitializing {
22 | | }
23 | | function _msgSender() internal view virtual returns (address) {
24 | | return msg.sender;
25 | | }
26 | |
27 | | function _msgData() internal view virtual returns (bytes calldata) {
28 | | return msg.data;
29 | | }
30 | |
31 | | /**
32 | | * @dev This empty reserved space is put in place to allow future versions to add new
33 | | * variables without shifting down storage in the inheritance chain.
34 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
35 | | */
36 | | uint256[50] private __gap;
37 | | }
38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/AccessControl.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./IAccessControl.sol";
7 | | import "../utils/Context.sol";
8 | | import "../utils/Strings.sol";
9 | | import "../utils/introspection/ERC165.sol";
10 | |
11 | | /**
12 | | * @dev Contract module that allows children to implement role-based access
13 | | * control mechanisms. This is a lightweight version that doesn't allow enumerating role
14 | | * members except through off-chain means by accessing the contract event logs. Some
15 | | * applications may benefit from on-chain enumerability, for those cases see
16 | | * {AccessControlEnumerable}.
17 | | *
18 | | * Roles are referred to by their `bytes32` identifier. These should be exposed
19 | | * in the external API and be unique. The best way to achieve this is by
20 | | * using `public constant` hash digests:
21 | | *
22 | | * ```solidity
23 | | * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
24 | | * ```
25 | | *
26 | | * Roles can be used to represent a set of permissions. To restrict access to a
27 | | * function call, use {hasRole}:
28 | | *
29 | | * ```solidity
30 | | * function foo() public {
31 | | * require(hasRole(MY_ROLE, msg.sender));
32 | | * ...
33 | | * }
34 | | * ```
35 | | *
36 | | * Roles can be granted and revoked dynamically via the {grantRole} and
37 | | * {revokeRole} functions. Each role has an associated admin role, and only
38 | | * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
39 | | *
40 | | * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
41 | | * that only accounts with this role will be able to grant or revoke other
42 | | * roles. More complex role relationships can be created by using
43 | | * {_setRoleAdmin}.
44 | | *
45 | | * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
46 | | * grant and revoke this role. Extra precautions should be taken to secure
47 | | * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
48 | | * to enforce additional security measures for this role.
49 | | */
50 | | abstract contract AccessControl is Context, IAccessControl, ERC165 {
51 | | struct RoleData {
52 | | mapping(address => bool) members;
53 | | bytes32 adminRole;
54 | | }
55 | |
56 | | mapping(bytes32 => RoleData) private _roles;
57 | |
58 | | bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
59 | |
60 | | /**
61 | | * @dev Modifier that checks that an account has a specific role. Reverts
62 | | * with a standardized message including the required role.
63 | | *
64 | | * The format of the revert reason is given by the following regular expression:
65 | | *
66 | | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
67 | | *
68 | | * _Available since v4.1._
69 | | */
70 | | modifier onlyRole(bytes32 role) {
71 | | _checkRole(role);
72 | | _;
73 | | }
74 | |
75 | | /**
76 | | * @dev See {IERC165-supportsInterface}.
77 | | */
78 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
79 | | return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
80 | | }
81 | |
82 | | /**
83 | | * @dev Returns `true` if `account` has been granted `role`.
84 | | */
85 | | function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
86 | | return _roles[role].members[account];
87 | | }
88 | |
89 | | /**
90 | | * @dev Revert with a standard message if `_msgSender()` is missing `role`.
91 | | * Overriding this function changes the behavior of the {onlyRole} modifier.
92 | | *
93 | | * Format of the revert message is described in {_checkRole}.
94 | | *
95 | | * _Available since v4.6._
96 | | */
97 | | function _checkRole(bytes32 role) internal view virtual {
98 | | _checkRole(role, _msgSender());
99 | | }
100 | |
101 | | /**
102 | | * @dev Revert with a standard message if `account` is missing `role`.
103 | | *
104 | | * The format of the revert reason is given by the following regular expression:
105 | | *
106 | | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
107 | | */
108 | | function _checkRole(bytes32 role, address account) internal view virtual {
109 | | if (!hasRole(role, account)) {
110 | | revert(
111 | | string(
112 | | abi.encodePacked(
113 | | "AccessControl: account ",
114 | | Strings.toHexString(account),
115 | | " is missing role ",
116 | | Strings.toHexString(uint256(role), 32)
117 | | )
118 | | )
119 | | );
120 | | }
121 | | }
122 | |
123 | | /**
124 | | * @dev Returns the admin role that controls `role`. See {grantRole} and
125 | | * {revokeRole}.
126 | | *
127 | | * To change a role's admin, use {_setRoleAdmin}.
128 | | */
129 | | function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
130 | | return _roles[role].adminRole;
131 | | }
132 | |
133 | | /**
134 | | * @dev Grants `role` to `account`.
135 | | *
136 | | * If `account` had not been already granted `role`, emits a {RoleGranted}
137 | | * event.
138 | | *
139 | | * Requirements:
140 | | *
141 | | * - the caller must have ``role``'s admin role.
142 | | *
143 | | * May emit a {RoleGranted} event.
144 | | */
145 | | function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
146 | | _grantRole(role, account);
147 | | }
148 | |
149 | | /**
150 | | * @dev Revokes `role` from `account`.
151 | | *
152 | | * If `account` had been granted `role`, emits a {RoleRevoked} event.
153 | | *
154 | | * Requirements:
155 | | *
156 | | * - the caller must have ``role``'s admin role.
157 | | *
158 | | * May emit a {RoleRevoked} event.
159 | | */
160 | | function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
161 | | _revokeRole(role, account);
162 | | }
163 | |
164 | | /**
165 | | * @dev Revokes `role` from the calling account.
166 | | *
167 | | * Roles are often managed via {grantRole} and {revokeRole}: this function's
168 | | * purpose is to provide a mechanism for accounts to lose their privileges
169 | | * if they are compromised (such as when a trusted device is misplaced).
170 | | *
171 | | * If the calling account had been revoked `role`, emits a {RoleRevoked}
172 | | * event.
173 | | *
174 | | * Requirements:
175 | | *
176 | | * - the caller must be `account`.
177 | | *
178 | | * May emit a {RoleRevoked} event.
179 | | */
180 | | function renounceRole(bytes32 role, address account) public virtual override {
181 | | require(account == _msgSender(), "AccessControl: can only renounce roles for self");
182 | |
183 | | _revokeRole(role, account);
184 | | }
185 | |
186 | | /**
187 | | * @dev Grants `role` to `account`.
188 | | *
189 | | * If `account` had not been already granted `role`, emits a {RoleGranted}
190 | | * event. Note that unlike {grantRole}, this function doesn't perform any
191 | | * checks on the calling account.
192 | | *
193 | | * May emit a {RoleGranted} event.
194 | | *
195 | | * [WARNING]
196 | | * ====
197 | | * This function should only be called from the constructor when setting
198 | | * up the initial roles for the system.
199 | | *
200 | | * Using this function in any other way is effectively circumventing the admin
201 | | * system imposed by {AccessControl}.
202 | | * ====
203 | | *
204 | | * NOTE: This function is deprecated in favor of {_grantRole}.
205 | | */
206 | | function _setupRole(bytes32 role, address account) internal virtual {
207 | | _grantRole(role, account);
208 | | }
209 | |
210 | | /**
211 | | * @dev Sets `adminRole` as ``role``'s admin role.
212 | | *
213 | | * Emits a {RoleAdminChanged} event.
214 | | */
215 | | function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
216 | | bytes32 previousAdminRole = getRoleAdmin(role);
217 | | _roles[role].adminRole = adminRole;
218 | | emit RoleAdminChanged(role, previousAdminRole, adminRole);
219 | | }
220 | |
221 | | /**
222 | | * @dev Grants `role` to `account`.
223 | | *
224 | | * Internal function without access restriction.
225 | | *
226 | | * May emit a {RoleGranted} event.
227 | | */
228 | | function _grantRole(bytes32 role, address account) internal virtual {
229 | | if (!hasRole(role, account)) {
230 | | _roles[role].members[account] = true;
231 | | emit RoleGranted(role, account, _msgSender());
232 | | }
233 | | }
234 | |
235 | | /**
236 | | * @dev Revokes `role` from `account`.
237 | | *
238 | | * Internal function without access restriction.
239 | | *
240 | | * May emit a {RoleRevoked} event.
241 | | */
242 | | function _revokeRole(bytes32 role, address account) internal virtual {
243 | | if (hasRole(role, account)) {
244 | | _roles[role].members[account] = false;
245 | | emit RoleRevoked(role, account, _msgSender());
246 | | }
247 | | }
248 | | }
249 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/IAccessControl.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev External interface of AccessControl declared to support ERC165 detection.
8 | | */
9 | | interface IAccessControl {
10 | | /**
11 | | * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
12 | | *
13 | | * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
14 | | * {RoleAdminChanged} not being emitted signaling this.
15 | | *
16 | | * _Available since v3.1._
17 | | */
18 | | event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
19 | |
20 | | /**
21 | | * @dev Emitted when `account` is granted `role`.
22 | | *
23 | | * `sender` is the account that originated the contract call, an admin role
24 | | * bearer except when using {AccessControl-_setupRole}.
25 | | */
26 | | event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
27 | |
28 | | /**
29 | | * @dev Emitted when `account` is revoked `role`.
30 | | *
31 | | * `sender` is the account that originated the contract call:
32 | | * - if using `revokeRole`, it is the admin role bearer
33 | | * - if using `renounceRole`, it is the role bearer (i.e. `account`)
34 | | */
35 | | event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
36 | |
37 | | /**
38 | | * @dev Returns `true` if `account` has been granted `role`.
39 | | */
40 | | function hasRole(bytes32 role, address account) external view returns (bool);
41 | |
42 | | /**
43 | | * @dev Returns the admin role that controls `role`. See {grantRole} and
44 | | * {revokeRole}.
45 | | *
46 | | * To change a role's admin, use {AccessControl-_setRoleAdmin}.
47 | | */
48 | | function getRoleAdmin(bytes32 role) external view returns (bytes32);
49 | |
50 | | /**
51 | | * @dev Grants `role` to `account`.
52 | | *
53 | | * If `account` had not been already granted `role`, emits a {RoleGranted}
54 | | * event.
55 | | *
56 | | * Requirements:
57 | | *
58 | | * - the caller must have ``role``'s admin role.
59 | | */
60 | | function grantRole(bytes32 role, address account) external;
61 | |
62 | | /**
63 | | * @dev Revokes `role` from `account`.
64 | | *
65 | | * If `account` had been granted `role`, emits a {RoleRevoked} event.
66 | | *
67 | | * Requirements:
68 | | *
69 | | * - the caller must have ``role``'s admin role.
70 | | */
71 | | function revokeRole(bytes32 role, address account) external;
72 | |
73 | | /**
74 | | * @dev Revokes `role` from the calling account.
75 | | *
76 | | * Roles are often managed via {grantRole} and {revokeRole}: this function's
77 | | * purpose is to provide a mechanism for accounts to lose their privileges
78 | | * if they are compromised (such as when a trusted device is misplaced).
79 | | *
80 | | * If the calling account had been granted `role`, emits a {RoleRevoked}
81 | | * event.
82 | | *
83 | | * Requirements:
84 | | *
85 | | * - the caller must be `account`.
86 | | */
87 | | function renounceRole(bytes32 role, address account) external;
88 | | }
89 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/Ownable.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../utils/Context.sol";
7 | |
8 | | /**
9 | | * @dev Contract module which provides a basic access control mechanism, where
10 | | * there is an account (an owner) that can be granted exclusive access to
11 | | * specific functions.
12 | | *
13 | | * By default, the owner account will be the one that deploys the contract. This
14 | | * can later be changed with {transferOwnership}.
15 | | *
16 | | * This module is used through inheritance. It will make available the modifier
17 | | * `onlyOwner`, which can be applied to your functions to restrict their use to
18 | | * the owner.
19 | | */
20 | | abstract contract Ownable is Context {
21 | | address private _owner;
22 | |
23 | | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
24 | |
25 | | /**
26 | | * @dev Initializes the contract setting the deployer as the initial owner.
27 | | */
28 | | constructor() {
29 | | _transferOwnership(_msgSender());
30 | | }
31 | |
32 | | /**
33 | | * @dev Throws if called by any account other than the owner.
34 | | */
35 | | modifier onlyOwner() {
36 | | _checkOwner();
37 | | _;
38 | | }
39 | |
40 | | /**
41 | | * @dev Returns the address of the current owner.
42 | | */
43 | | function owner() public view virtual returns (address) {
44 | | return _owner;
45 | | }
46 | |
47 | | /**
48 | | * @dev Throws if the sender is not the owner.
49 | | */
50 | | function _checkOwner() internal view virtual {
51 | | require(owner() == _msgSender(), "Ownable: caller is not the owner");
52 | | }
53 | |
54 | | /**
55 | | * @dev Leaves the contract without owner. It will not be possible to call
56 | | * `onlyOwner` functions. Can only be called by the current owner.
57 | | *
58 | | * NOTE: Renouncing ownership will leave the contract without an owner,
59 | | * thereby disabling any functionality that is only available to the owner.
60 | | */
61 | | function renounceOwnership() public virtual onlyOwner {
62 | | _transferOwnership(address(0));
63 | | }
64 | |
65 | | /**
66 | | * @dev Transfers ownership of the contract to a new account (`newOwner`).
67 | | * Can only be called by the current owner.
68 | | */
69 | | function transferOwnership(address newOwner) public virtual onlyOwner {
70 | | require(newOwner != address(0), "Ownable: new owner is the zero address");
71 | | _transferOwnership(newOwner);
72 | | }
73 | |
74 | | /**
75 | | * @dev Transfers ownership of the contract to a new account (`newOwner`).
76 | | * Internal function without access restriction.
77 | | */
78 | | function _transferOwnership(address newOwner) internal virtual {
79 | | address oldOwner = _owner;
80 | | _owner = newOwner;
81 | | emit OwnershipTransferred(oldOwner, newOwner);
82 | | }
83 | | }
84 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/Governor.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.1) (governance/Governor.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../token/ERC721/IERC721Receiver.sol";
7 | | import "../token/ERC1155/IERC1155Receiver.sol";
8 | | import "../utils/cryptography/ECDSA.sol";
9 | | import "../utils/cryptography/EIP712.sol";
10 | | import "../utils/introspection/ERC165.sol";
11 | | import "../utils/math/SafeCast.sol";
12 | | import "../utils/structs/DoubleEndedQueue.sol";
13 | | import "../utils/Address.sol";
14 | | import "../utils/Context.sol";
15 | | import "./IGovernor.sol";
16 | |
17 | | /**
18 | | * @dev Core of the governance system, designed to be extended though various modules.
19 | | *
20 | | * This contract is abstract and requires several functions to be implemented in various modules:
21 | | *
22 | | * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}
23 | | * - A voting module must implement {_getVotes}
24 | | * - Additionally, {votingPeriod} must also be implemented
25 | | *
26 | | * _Available since v4.3._
27 | | */
28 | | abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {
29 | | using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
30 | |
31 | | bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
32 | | bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
33 | | keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");
34 | |
35 | | // solhint-disable var-name-mixedcase
36 | | struct ProposalCore {
37 | | // --- start retyped from Timers.BlockNumber at offset 0x00 ---
38 | | uint64 voteStart;
39 | | address proposer;
40 | | bytes4 __gap_unused0;
41 | | // --- start retyped from Timers.BlockNumber at offset 0x20 ---
42 | | uint64 voteEnd;
43 | | bytes24 __gap_unused1;
44 | | // --- Remaining fields starting at offset 0x40 ---------------
45 | | bool executed;
46 | | bool canceled;
47 | | }
48 | | // solhint-enable var-name-mixedcase
49 | |
50 | | string private _name;
51 | |
52 | | /// @custom:oz-retyped-from mapping(uint256 => Governor.ProposalCore)
53 | | mapping(uint256 => ProposalCore) private _proposals;
54 | |
55 | | // This queue keeps track of the governor operating on itself. Calls to functions protected by the
56 | | // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},
57 | | // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the
58 | | // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
59 | | DoubleEndedQueue.Bytes32Deque private _governanceCall;
60 | |
61 | | /**
62 | | * @dev Restricts a function so it can only be executed through governance proposals. For example, governance
63 | | * parameter setters in {GovernorSettings} are protected using this modifier.
64 | | *
65 | | * The governance executing address may be different from the Governor's own address, for example it could be a
66 | | * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these
67 | | * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,
68 | | * for example, additional timelock proposers are not able to change governance parameters without going through the
69 | | * governance protocol (since v4.6).
70 | | */
71 | | modifier onlyGovernance() {
72 | | require(_msgSender() == _executor(), "Governor: onlyGovernance");
73 | | if (_executor() != address(this)) {
74 | | bytes32 msgDataHash = keccak256(_msgData());
75 | | // loop until popping the expected operation - throw if deque is empty (operation not authorized)
76 | | while (_governanceCall.popFront() != msgDataHash) {}
77 | | }
78 | | _;
79 | | }
80 | |
81 | | /**
82 | | * @dev Sets the value for {name} and {version}
83 | | */
84 | | constructor(string memory name_) EIP712(name_, version()) {
85 | | _name = name_;
86 | | }
87 | |
88 | | /**
89 | | * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
90 | | */
91 | | receive() external payable virtual {
92 | | require(_executor() == address(this), "Governor: must send to executor");
93 | | }
94 | |
95 | | /**
96 | | * @dev See {IERC165-supportsInterface}.
97 | | */
98 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
99 | | bytes4 governorCancelId = this.cancel.selector ^ this.proposalProposer.selector;
100 | |
101 | | bytes4 governorParamsId = this.castVoteWithReasonAndParams.selector ^
102 | | this.castVoteWithReasonAndParamsBySig.selector ^
103 | | this.getVotesWithParams.selector;
104 | |
105 | | // The original interface id in v4.3.
106 | | bytes4 governor43Id = type(IGovernor).interfaceId ^
107 | | type(IERC6372).interfaceId ^
108 | | governorCancelId ^
109 | | governorParamsId;
110 | |
111 | | // An updated interface id in v4.6, with params added.
112 | | bytes4 governor46Id = type(IGovernor).interfaceId ^ type(IERC6372).interfaceId ^ governorCancelId;
113 | |
114 | | // For the updated interface id in v4.9, we use governorCancelId directly.
115 | |
116 | | return
117 | | interfaceId == governor43Id ||
118 | | interfaceId == governor46Id ||
119 | | interfaceId == governorCancelId ||
120 | | interfaceId == type(IERC1155Receiver).interfaceId ||
121 | | super.supportsInterface(interfaceId);
122 | | }
123 | |
124 | | /**
125 | | * @dev See {IGovernor-name}.
126 | | */
127 | | function name() public view virtual override returns (string memory) {
128 | | return _name;
129 | | }
130 | |
131 | | /**
132 | | * @dev See {IGovernor-version}.
133 | | */
134 | | function version() public view virtual override returns (string memory) {
135 | | return "1";
136 | | }
137 | |
138 | | /**
139 | | * @dev See {IGovernor-hashProposal}.
140 | | *
141 | | * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array
142 | | * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
143 | | * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
144 | | * advance, before the proposal is submitted.
145 | | *
146 | | * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
147 | | * same proposal (with same operation and same description) will have the same id if submitted on multiple governors
148 | | * across multiple networks. This also means that in order to execute the same operation twice (on the same
149 | | * governor) the proposer will have to change the description in order to avoid proposal id conflicts.
150 | | */
151 | | function hashProposal(
152 | | address[] memory targets,
153 | | uint256[] memory values,
154 | | bytes[] memory calldatas,
155 | | bytes32 descriptionHash
156 | | ) public pure virtual override returns (uint256) {
157 | | return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
158 | | }
159 | |
160 | | /**
161 | | * @dev See {IGovernor-state}.
162 | | */
163 | | function state(uint256 proposalId) public view virtual override returns (ProposalState) {
164 | | ProposalCore storage proposal = _proposals[proposalId];
165 | |
166 | | if (proposal.executed) {
167 | | return ProposalState.Executed;
168 | | }
169 | |
170 | | if (proposal.canceled) {
171 | | return ProposalState.Canceled;
172 | | }
173 | |
174 | | uint256 snapshot = proposalSnapshot(proposalId);
175 | |
176 | | if (snapshot == 0) {
177 | | revert("Governor: unknown proposal id");
178 | | }
179 | |
180 | | uint256 currentTimepoint = clock();
181 | |
182 | | if (snapshot >= currentTimepoint) {
183 | | return ProposalState.Pending;
184 | | }
185 | |
186 | | uint256 deadline = proposalDeadline(proposalId);
187 | |
188 | | if (deadline >= currentTimepoint) {
189 | | return ProposalState.Active;
190 | | }
191 | |
192 | | if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
193 | | return ProposalState.Succeeded;
194 | | } else {
195 | | return ProposalState.Defeated;
196 | | }
197 | | }
198 | |
199 | | /**
200 | | * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
201 | | */
202 | | function proposalThreshold() public view virtual returns (uint256) {
203 | | return 0;
204 | | }
205 | |
206 | | /**
207 | | * @dev See {IGovernor-proposalSnapshot}.
208 | | */
209 | | function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
210 | | return _proposals[proposalId].voteStart;
211 | | }
212 | |
213 | | /**
214 | | * @dev See {IGovernor-proposalDeadline}.
215 | | */
216 | | function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
217 | | return _proposals[proposalId].voteEnd;
218 | | }
219 | |
220 | | /**
221 | | * @dev Returns the account that created a given proposal.
222 | | */
223 | | function proposalProposer(uint256 proposalId) public view virtual override returns (address) {
224 | | return _proposals[proposalId].proposer;
225 | | }
226 | |
227 | | /**
228 | | * @dev Amount of votes already cast passes the threshold limit.
229 | | */
230 | | function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
231 | |
232 | | /**
233 | | * @dev Is the proposal successful or not.
234 | | */
235 | | function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
236 | |
237 | | /**
238 | | * @dev Get the voting weight of `account` at a specific `timepoint`, for a vote as described by `params`.
239 | | */
240 | | function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256);
241 | |
242 | | /**
243 | | * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`.
244 | | *
245 | | * Note: Support is generic and can represent various things depending on the voting system used.
246 | | */
247 | | function _countVote(
248 | | uint256 proposalId,
249 | | address account,
250 | | uint8 support,
251 | | uint256 weight,
252 | | bytes memory params
253 | | ) internal virtual;
254 | |
255 | | /**
256 | | * @dev Default additional encoded parameters used by castVote methods that don't include them
257 | | *
258 | | * Note: Should be overridden by specific implementations to use an appropriate value, the
259 | | * meaning of the additional params, in the context of that implementation
260 | | */
261 | | function _defaultParams() internal view virtual returns (bytes memory) {
262 | | return "";
263 | | }
264 | |
265 | | /**
266 | | * @dev See {IGovernor-propose}. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}.
267 | | */
268 | | function propose(
269 | | address[] memory targets,
270 | | uint256[] memory values,
271 | | bytes[] memory calldatas,
272 | | string memory description
273 | | ) public virtual override returns (uint256) {
274 | | address proposer = _msgSender();
275 | | require(_isValidDescriptionForProposer(proposer, description), "Governor: proposer restricted");
276 | |
277 | | uint256 currentTimepoint = clock();
278 | | require(
279 | | getVotes(proposer, currentTimepoint - 1) >= proposalThreshold(),
280 | | "Governor: proposer votes below proposal threshold"
281 | | );
282 | |
283 | | uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
284 | |
285 | | require(targets.length == values.length, "Governor: invalid proposal length");
286 | | require(targets.length == calldatas.length, "Governor: invalid proposal length");
287 | | require(targets.length > 0, "Governor: empty proposal");
288 | | require(_proposals[proposalId].voteStart == 0, "Governor: proposal already exists");
289 | |
290 | | uint256 snapshot = currentTimepoint + votingDelay();
291 | | uint256 deadline = snapshot + votingPeriod();
292 | |
293 | | _proposals[proposalId] = ProposalCore({
294 | | proposer: proposer,
295 | | voteStart: SafeCast.toUint64(snapshot),
296 | | voteEnd: SafeCast.toUint64(deadline),
297 | | executed: false,
298 | | canceled: false,
299 | | __gap_unused0: 0,
300 | | __gap_unused1: 0
301 | | });
302 | |
303 | | emit ProposalCreated(
304 | | proposalId,
305 | | proposer,
306 | | targets,
307 | | values,
308 | | new string[](targets.length),
309 | | calldatas,
310 | | snapshot,
311 | | deadline,
312 | | description
313 | | );
314 | |
315 | | return proposalId;
316 | | }
317 | |
318 | | /**
319 | | * @dev See {IGovernor-execute}.
320 | | */
321 | | function execute(
322 | | address[] memory targets,
323 | | uint256[] memory values,
324 | | bytes[] memory calldatas,
325 | | bytes32 descriptionHash
326 | | ) public payable virtual override returns (uint256) {
327 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
328 | |
329 | | ProposalState currentState = state(proposalId);
330 | | require(
331 | | currentState == ProposalState.Succeeded || currentState == ProposalState.Queued,
332 | | "Governor: proposal not successful"
333 | | );
334 | | _proposals[proposalId].executed = true;
335 | |
336 | | emit ProposalExecuted(proposalId);
337 | |
338 | | _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
339 | | _execute(proposalId, targets, values, calldatas, descriptionHash);
340 | | _afterExecute(proposalId, targets, values, calldatas, descriptionHash);
341 | |
342 | | return proposalId;
343 | | }
344 | |
345 | | /**
346 | | * @dev See {IGovernor-cancel}.
347 | | */
348 | | function cancel(
349 | | address[] memory targets,
350 | | uint256[] memory values,
351 | | bytes[] memory calldatas,
352 | | bytes32 descriptionHash
353 | | ) public virtual override returns (uint256) {
354 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
355 | | require(state(proposalId) == ProposalState.Pending, "Governor: too late to cancel");
356 | | require(_msgSender() == _proposals[proposalId].proposer, "Governor: only proposer can cancel");
357 | | return _cancel(targets, values, calldatas, descriptionHash);
358 | | }
359 | |
360 | | /**
361 | | * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism
362 | | */
363 | | function _execute(
364 | | uint256 /* proposalId */,
365 | | address[] memory targets,
366 | | uint256[] memory values,
367 | | bytes[] memory calldatas,
368 | | bytes32 /*descriptionHash*/
369 | | ) internal virtual {
370 | | string memory errorMessage = "Governor: call reverted without message";
371 | | for (uint256 i = 0; i < targets.length; ++i) {
372 | | (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
373 | | Address.verifyCallResult(success, returndata, errorMessage);
374 | | }
375 | | }
376 | |
377 | | /**
378 | | * @dev Hook before execution is triggered.
379 | | */
380 | | function _beforeExecute(
381 | | uint256 /* proposalId */,
382 | | address[] memory targets,
383 | | uint256[] memory /* values */,
384 | | bytes[] memory calldatas,
385 | | bytes32 /*descriptionHash*/
386 | | ) internal virtual {
387 | | if (_executor() != address(this)) {
388 | | for (uint256 i = 0; i < targets.length; ++i) {
389 | | if (targets[i] == address(this)) {
390 | | _governanceCall.pushBack(keccak256(calldatas[i]));
391 | | }
392 | | }
393 | | }
394 | | }
395 | |
396 | | /**
397 | | * @dev Hook after execution is triggered.
398 | | */
399 | | function _afterExecute(
400 | | uint256 /* proposalId */,
401 | | address[] memory /* targets */,
402 | | uint256[] memory /* values */,
403 | | bytes[] memory /* calldatas */,
404 | | bytes32 /*descriptionHash*/
405 | | ) internal virtual {
406 | | if (_executor() != address(this)) {
407 | | if (!_governanceCall.empty()) {
408 | | _governanceCall.clear();
409 | | }
410 | | }
411 | | }
412 | |
413 | | /**
414 | | * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
415 | | * canceled to allow distinguishing it from executed proposals.
416 | | *
417 | | * Emits a {IGovernor-ProposalCanceled} event.
418 | | */
419 | | function _cancel(
420 | | address[] memory targets,
421 | | uint256[] memory values,
422 | | bytes[] memory calldatas,
423 | | bytes32 descriptionHash
424 | | ) internal virtual returns (uint256) {
425 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
426 | |
427 | | ProposalState currentState = state(proposalId);
428 | |
429 | | require(
430 | | currentState != ProposalState.Canceled &&
431 | | currentState != ProposalState.Expired &&
432 | | currentState != ProposalState.Executed,
433 | | "Governor: proposal not active"
434 | | );
435 | | _proposals[proposalId].canceled = true;
436 | |
437 | | emit ProposalCanceled(proposalId);
438 | |
439 | | return proposalId;
440 | | }
441 | |
442 | | /**
443 | | * @dev See {IGovernor-getVotes}.
444 | | */
445 | | function getVotes(address account, uint256 timepoint) public view virtual override returns (uint256) {
446 | | return _getVotes(account, timepoint, _defaultParams());
447 | | }
448 | |
449 | | /**
450 | | * @dev See {IGovernor-getVotesWithParams}.
451 | | */
452 | | function getVotesWithParams(
453 | | address account,
454 | | uint256 timepoint,
455 | | bytes memory params
456 | | ) public view virtual override returns (uint256) {
457 | | return _getVotes(account, timepoint, params);
458 | | }
459 | |
460 | | /**
461 | | * @dev See {IGovernor-castVote}.
462 | | */
463 | | function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {
464 | | address voter = _msgSender();
465 | | return _castVote(proposalId, voter, support, "");
466 | | }
467 | |
468 | | /**
469 | | * @dev See {IGovernor-castVoteWithReason}.
470 | | */
471 | | function castVoteWithReason(
472 | | uint256 proposalId,
473 | | uint8 support,
474 | | string calldata reason
475 | | ) public virtual override returns (uint256) {
476 | | address voter = _msgSender();
477 | | return _castVote(proposalId, voter, support, reason);
478 | | }
479 | |
480 | | /**
481 | | * @dev See {IGovernor-castVoteWithReasonAndParams}.
482 | | */
483 | | function castVoteWithReasonAndParams(
484 | | uint256 proposalId,
485 | | uint8 support,
486 | | string calldata reason,
487 | | bytes memory params
488 | | ) public virtual override returns (uint256) {
489 | | address voter = _msgSender();
490 | | return _castVote(proposalId, voter, support, reason, params);
491 | | }
492 | |
493 | | /**
494 | | * @dev See {IGovernor-castVoteBySig}.
495 | | */
496 | | function castVoteBySig(
497 | | uint256 proposalId,
498 | | uint8 support,
499 | | uint8 v,
500 | | bytes32 r,
501 | | bytes32 s
502 | | ) public virtual override returns (uint256) {
503 | | address voter = ECDSA.recover(
504 | | _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
505 | | v,
506 | | r,
507 | | s
508 | | );
509 | | return _castVote(proposalId, voter, support, "");
510 | | }
511 | |
512 | | /**
513 | | * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.
514 | | */
515 | | function castVoteWithReasonAndParamsBySig(
516 | | uint256 proposalId,
517 | | uint8 support,
518 | | string calldata reason,
519 | | bytes memory params,
520 | | uint8 v,
521 | | bytes32 r,
522 | | bytes32 s
523 | | ) public virtual override returns (uint256) {
524 | | address voter = ECDSA.recover(
525 | | _hashTypedDataV4(
526 | | keccak256(
527 | | abi.encode(
528 | | EXTENDED_BALLOT_TYPEHASH,
529 | | proposalId,
530 | | support,
531 | | keccak256(bytes(reason)),
532 | | keccak256(params)
533 | | )
534 | | )
535 | | ),
536 | | v,
537 | | r,
538 | | s
539 | | );
540 | |
541 | | return _castVote(proposalId, voter, support, reason, params);
542 | | }
543 | |
544 | | /**
545 | | * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
546 | | * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
547 | | *
548 | | * Emits a {IGovernor-VoteCast} event.
549 | | */
550 | | function _castVote(
551 | | uint256 proposalId,
552 | | address account,
553 | | uint8 support,
554 | | string memory reason
555 | | ) internal virtual returns (uint256) {
556 | | return _castVote(proposalId, account, support, reason, _defaultParams());
557 | | }
558 | |
559 | | /**
560 | | * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
561 | | * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
562 | | *
563 | | * Emits a {IGovernor-VoteCast} event.
564 | | */
565 | | function _castVote(
566 | | uint256 proposalId,
567 | | address account,
568 | | uint8 support,
569 | | string memory reason,
570 | | bytes memory params
571 | | ) internal virtual returns (uint256) {
572 | | ProposalCore storage proposal = _proposals[proposalId];
573 | | require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");
574 | |
575 | | uint256 weight = _getVotes(account, proposal.voteStart, params);
576 | | _countVote(proposalId, account, support, weight, params);
577 | |
578 | | if (params.length == 0) {
579 | | emit VoteCast(account, proposalId, support, weight, reason);
580 | | } else {
581 | | emit VoteCastWithParams(account, proposalId, support, weight, reason, params);
582 | | }
583 | |
584 | | return weight;
585 | | }
586 | |
587 | | /**
588 | | * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor
589 | | * is some contract other than the governor itself, like when using a timelock, this function can be invoked
590 | | * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.
591 | | * Note that if the executor is simply the governor itself, use of `relay` is redundant.
592 | | */
593 | | function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance {
594 | | (bool success, bytes memory returndata) = target.call{value: value}(data);
595 | | Address.verifyCallResult(success, returndata, "Governor: relay reverted without message");
596 | | }
597 | |
598 | | /**
599 | | * @dev Address through which the governor executes action. Will be overloaded by module that execute actions
600 | | * through another contract such as a timelock.
601 | | */
602 | | function _executor() internal view virtual returns (address) {
603 | | return address(this);
604 | | }
605 | |
606 | | /**
607 | | * @dev See {IERC721Receiver-onERC721Received}.
608 | | */
609 | | function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
610 | | return this.onERC721Received.selector;
611 | | }
612 | |
613 | | /**
614 | | * @dev See {IERC1155Receiver-onERC1155Received}.
615 | | */
616 | | function onERC1155Received(
617 | | address,
618 | | address,
619 | | uint256,
620 | | uint256,
621 | | bytes memory
622 | | ) public virtual override returns (bytes4) {
623 | | return this.onERC1155Received.selector;
624 | | }
625 | |
626 | | /**
627 | | * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
628 | | */
629 | | function onERC1155BatchReceived(
630 | | address,
631 | | address,
632 | | uint256[] memory,
633 | | uint256[] memory,
634 | | bytes memory
635 | | ) public virtual override returns (bytes4) {
636 | | return this.onERC1155BatchReceived.selector;
637 | | }
638 | |
639 | | /**
640 | | * @dev Check if the proposer is authorized to submit a proposal with the given description.
641 | | *
642 | | * If the proposal description ends with `#proposer=0x???`, where `0x???` is an address written as a hex string
643 | | * (case insensitive), then the submission of this proposal will only be authorized to said address.
644 | | *
645 | | * This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure
646 | | * that no other address can submit the same proposal. An attacker would have to either remove or change that part,
647 | | * which would result in a different proposal id.
648 | | *
649 | | * If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes:
650 | | * - If the `0x???` part is not a valid hex string.
651 | | * - If the `0x???` part is a valid hex string, but does not contain exactly 40 hex digits.
652 | | * - If it ends with the expected suffix followed by newlines or other whitespace.
653 | | * - If it ends with some other similar suffix, e.g. `#other=abc`.
654 | | * - If it does not end with any such suffix.
655 | | */
656 | | function _isValidDescriptionForProposer(
657 | | address proposer,
658 | | string memory description
659 | | ) internal view virtual returns (bool) {
660 | | uint256 len = bytes(description).length;
661 | |
662 | | // Length is too short to contain a valid proposer suffix
663 | | if (len < 52) {
664 | | return true;
665 | | }
666 | |
667 | | // Extract what would be the `#proposer=0x` marker beginning the suffix
668 | | bytes12 marker;
669 | | assembly {
670 | | // - Start of the string contents in memory = description + 32
671 | | // - First character of the marker = len - 52
672 | | // - Length of "#proposer=0x0000000000000000000000000000000000000000" = 52
673 | | // - We read the memory word starting at the first character of the marker:
674 | | // - (description + 32) + (len - 52) = description + (len - 20)
675 | | // - Note: Solidity will ignore anything past the first 12 bytes
676 | | marker := mload(add(description, sub(len, 20)))
677 | | }
678 | |
679 | | // If the marker is not found, there is no proposer suffix to check
680 | | if (marker != bytes12("#proposer=0x")) {
681 | | return true;
682 | | }
683 | |
684 | | // Parse the 40 characters following the marker as uint160
685 | | uint160 recovered = 0;
686 | | for (uint256 i = len - 40; i < len; ++i) {
687 | | (bool isHex, uint8 value) = _tryHexToUint(bytes(description)[i]);
688 | | // If any of the characters is not a hex digit, ignore the suffix entirely
689 | | if (!isHex) {
690 | | return true;
691 | | }
692 | | recovered = (recovered << 4) | value;
693 | | }
694 | |
695 | | return recovered == uint160(proposer);
696 | | }
697 | |
698 | | /**
699 | | * @dev Try to parse a character from a string as a hex value. Returns `(true, value)` if the char is in
700 | | * `[0-9a-fA-F]` and `(false, 0)` otherwise. Value is guaranteed to be in the range `0 <= value < 16`
701 | | */
702 | | function _tryHexToUint(bytes1 char) private pure returns (bool, uint8) {
703 | | uint8 c = uint8(char);
704 | | unchecked {
705 | | // Case 0-9
706 | | if (47 < c && c < 58) {
707 | | return (true, c - 48);
708 | | }
709 | | // Case A-F
710 | | else if (64 < c && c < 71) {
711 | | return (true, c - 55);
712 | | }
713 | | // Case a-f
714 | | else if (96 < c && c < 103) {
715 | | return (true, c - 87);
716 | | }
717 | | // Else: not a hex char
718 | | else {
719 | | return (false, 0);
720 | | }
721 | | }
722 | | }
723 | | }
724 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/IGovernor.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/IGovernor.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../interfaces/IERC165.sol";
7 | | import "../interfaces/IERC6372.sol";
8 | |
9 | | /**
10 | | * @dev Interface of the {Governor} core.
11 | | *
12 | | * _Available since v4.3._
13 | | */
14 | | abstract contract IGovernor is IERC165, IERC6372 {
15 | | enum ProposalState {
16 | | Pending,
17 | | Active,
18 | | Canceled,
19 | | Defeated,
20 | | Succeeded,
21 | | Queued,
22 | | Expired,
23 | | Executed
24 | | }
25 | |
26 | | /**
27 | | * @dev Emitted when a proposal is created.
28 | | */
29 | | event ProposalCreated(
30 | | uint256 proposalId,
31 | | address proposer,
32 | | address[] targets,
33 | | uint256[] values,
34 | | string[] signatures,
35 | | bytes[] calldatas,
36 | | uint256 voteStart,
37 | | uint256 voteEnd,
38 | | string description
39 | | );
40 | |
41 | | /**
42 | | * @dev Emitted when a proposal is canceled.
43 | | */
44 | | event ProposalCanceled(uint256 proposalId);
45 | |
46 | | /**
47 | | * @dev Emitted when a proposal is executed.
48 | | */
49 | | event ProposalExecuted(uint256 proposalId);
50 | |
51 | | /**
52 | | * @dev Emitted when a vote is cast without params.
53 | | *
54 | | * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
55 | | */
56 | | event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
57 | |
58 | | /**
59 | | * @dev Emitted when a vote is cast with params.
60 | | *
61 | | * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
62 | | * `params` are additional encoded parameters. Their interpepretation also depends on the voting module used.
63 | | */
64 | | event VoteCastWithParams(
65 | | address indexed voter,
66 | | uint256 proposalId,
67 | | uint8 support,
68 | | uint256 weight,
69 | | string reason,
70 | | bytes params
71 | | );
72 | |
73 | | /**
74 | | * @notice module:core
75 | | * @dev Name of the governor instance (used in building the ERC712 domain separator).
76 | | */
77 | | function name() public view virtual returns (string memory);
78 | |
79 | | /**
80 | | * @notice module:core
81 | | * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
82 | | */
83 | | function version() public view virtual returns (string memory);
84 | |
85 | | /**
86 | | * @notice module:core
87 | | * @dev See {IERC6372}
88 | | */
89 | | function clock() public view virtual override returns (uint48);
90 | |
91 | | /**
92 | | * @notice module:core
93 | | * @dev See EIP-6372.
94 | | */
95 | | // solhint-disable-next-line func-name-mixedcase
96 | | function CLOCK_MODE() public view virtual override returns (string memory);
97 | |
98 | | /**
99 | | * @notice module:voting
100 | | * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
101 | | * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
102 | | * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
103 | | *
104 | | * There are 2 standard keys: `support` and `quorum`.
105 | | *
106 | | * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
107 | | * - `quorum=bravo` means that only For votes are counted towards quorum.
108 | | * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
109 | | *
110 | | * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique
111 | | * name that describes the behavior. For example:
112 | | *
113 | | * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
114 | | * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
115 | | *
116 | | * NOTE: The string can be decoded by the standard
117 | | * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
118 | | * JavaScript class.
119 | | */
120 | | // solhint-disable-next-line func-name-mixedcase
121 | | function COUNTING_MODE() public view virtual returns (string memory);
122 | |
123 | | /**
124 | | * @notice module:core
125 | | * @dev Hashing function used to (re)build the proposal id from the proposal details..
126 | | */
127 | | function hashProposal(
128 | | address[] memory targets,
129 | | uint256[] memory values,
130 | | bytes[] memory calldatas,
131 | | bytes32 descriptionHash
132 | | ) public pure virtual returns (uint256);
133 | |
134 | | /**
135 | | * @notice module:core
136 | | * @dev Current state of a proposal, following Compound's convention
137 | | */
138 | | function state(uint256 proposalId) public view virtual returns (ProposalState);
139 | |
140 | | /**
141 | | * @notice module:core
142 | | * @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the
143 | | * snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the
144 | | * following block.
145 | | */
146 | | function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);
147 | |
148 | | /**
149 | | * @notice module:core
150 | | * @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is
151 | | * possible to cast a vote during this block.
152 | | */
153 | | function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);
154 | |
155 | | /**
156 | | * @notice module:core
157 | | * @dev The account that created a proposal.
158 | | */
159 | | function proposalProposer(uint256 proposalId) public view virtual returns (address);
160 | |
161 | | /**
162 | | * @notice module:user-config
163 | | * @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends
164 | | * on the clock (see EIP-6372) this contract uses.
165 | | *
166 | | * This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a
167 | | * proposal starts.
168 | | */
169 | | function votingDelay() public view virtual returns (uint256);
170 | |
171 | | /**
172 | | * @notice module:user-config
173 | | * @dev Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock
174 | | * (see EIP-6372) this contract uses.
175 | | *
176 | | * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
177 | | * duration compared to the voting delay.
178 | | */
179 | | function votingPeriod() public view virtual returns (uint256);
180 | |
181 | | /**
182 | | * @notice module:user-config
183 | | * @dev Minimum number of cast voted required for a proposal to be successful.
184 | | *
185 | | * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the
186 | | * quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}).
187 | | */
188 | | function quorum(uint256 timepoint) public view virtual returns (uint256);
189 | |
190 | | /**
191 | | * @notice module:reputation
192 | | * @dev Voting power of an `account` at a specific `timepoint`.
193 | | *
194 | | * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
195 | | * multiple), {ERC20Votes} tokens.
196 | | */
197 | | function getVotes(address account, uint256 timepoint) public view virtual returns (uint256);
198 | |
199 | | /**
200 | | * @notice module:reputation
201 | | * @dev Voting power of an `account` at a specific `timepoint` given additional encoded parameters.
202 | | */
203 | | function getVotesWithParams(
204 | | address account,
205 | | uint256 timepoint,
206 | | bytes memory params
207 | | ) public view virtual returns (uint256);
208 | |
209 | | /**
210 | | * @notice module:voting
211 | | * @dev Returns whether `account` has cast a vote on `proposalId`.
212 | | */
213 | | function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);
214 | |
215 | | /**
216 | | * @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a
217 | | * duration specified by {IGovernor-votingPeriod}.
218 | | *
219 | | * Emits a {ProposalCreated} event.
220 | | */
221 | | function propose(
222 | | address[] memory targets,
223 | | uint256[] memory values,
224 | | bytes[] memory calldatas,
225 | | string memory description
226 | | ) public virtual returns (uint256 proposalId);
227 | |
228 | | /**
229 | | * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
230 | | * deadline to be reached.
231 | | *
232 | | * Emits a {ProposalExecuted} event.
233 | | *
234 | | * Note: some module can modify the requirements for execution, for example by adding an additional timelock.
235 | | */
236 | | function execute(
237 | | address[] memory targets,
238 | | uint256[] memory values,
239 | | bytes[] memory calldatas,
240 | | bytes32 descriptionHash
241 | | ) public payable virtual returns (uint256 proposalId);
242 | |
243 | | /**
244 | | * @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e.
245 | | * before the vote starts.
246 | | *
247 | | * Emits a {ProposalCanceled} event.
248 | | */
249 | | function cancel(
250 | | address[] memory targets,
251 | | uint256[] memory values,
252 | | bytes[] memory calldatas,
253 | | bytes32 descriptionHash
254 | | ) public virtual returns (uint256 proposalId);
255 | |
256 | | /**
257 | | * @dev Cast a vote
258 | | *
259 | | * Emits a {VoteCast} event.
260 | | */
261 | | function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);
262 | |
263 | | /**
264 | | * @dev Cast a vote with a reason
265 | | *
266 | | * Emits a {VoteCast} event.
267 | | */
268 | | function castVoteWithReason(
269 | | uint256 proposalId,
270 | | uint8 support,
271 | | string calldata reason
272 | | ) public virtual returns (uint256 balance);
273 | |
274 | | /**
275 | | * @dev Cast a vote with a reason and additional encoded parameters
276 | | *
277 | | * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
278 | | */
279 | | function castVoteWithReasonAndParams(
280 | | uint256 proposalId,
281 | | uint8 support,
282 | | string calldata reason,
283 | | bytes memory params
284 | | ) public virtual returns (uint256 balance);
285 | |
286 | | /**
287 | | * @dev Cast a vote using the user's cryptographic signature.
288 | | *
289 | | * Emits a {VoteCast} event.
290 | | */
291 | | function castVoteBySig(
292 | | uint256 proposalId,
293 | | uint8 support,
294 | | uint8 v,
295 | | bytes32 r,
296 | | bytes32 s
297 | | ) public virtual returns (uint256 balance);
298 | |
299 | | /**
300 | | * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
301 | | *
302 | | * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
303 | | */
304 | | function castVoteWithReasonAndParamsBySig(
305 | | uint256 proposalId,
306 | | uint8 support,
307 | | string calldata reason,
308 | | bytes memory params,
309 | | uint8 v,
310 | | bytes32 r,
311 | | bytes32 s
312 | | ) public virtual returns (uint256 balance);
313 | | }
314 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/TimelockController.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../access/AccessControl.sol";
7 | | import "../token/ERC721/IERC721Receiver.sol";
8 | | import "../token/ERC1155/IERC1155Receiver.sol";
9 | |
10 | | /**
11 | | * @dev Contract module which acts as a timelocked controller. When set as the
12 | | * owner of an `Ownable` smart contract, it enforces a timelock on all
13 | | * `onlyOwner` maintenance operations. This gives time for users of the
14 | | * controlled contract to exit before a potentially dangerous maintenance
15 | | * operation is applied.
16 | | *
17 | | * By default, this contract is self administered, meaning administration tasks
18 | | * have to go through the timelock process. The proposer (resp executor) role
19 | | * is in charge of proposing (resp executing) operations. A common use case is
20 | | * to position this {TimelockController} as the owner of a smart contract, with
21 | | * a multisig or a DAO as the sole proposer.
22 | | *
23 | | * _Available since v3.3._
24 | | */
25 | | contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {
26 | | bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
27 | | bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
28 | | bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
29 | | bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
30 | | uint256 internal constant _DONE_TIMESTAMP = uint256(1);
31 | |
32 | | mapping(bytes32 => uint256) private _timestamps;
33 | | uint256 private _minDelay;
34 | |
35 | | /**
36 | | * @dev Emitted when a call is scheduled as part of operation `id`.
37 | | */
38 | | event CallScheduled(
39 | | bytes32 indexed id,
40 | | uint256 indexed index,
41 | | address target,
42 | | uint256 value,
43 | | bytes data,
44 | | bytes32 predecessor,
45 | | uint256 delay
46 | | );
47 | |
48 | | /**
49 | | * @dev Emitted when a call is performed as part of operation `id`.
50 | | */
51 | | event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
52 | |
53 | | /**
54 | | * @dev Emitted when new proposal is scheduled with non-zero salt.
55 | | */
56 | | event CallSalt(bytes32 indexed id, bytes32 salt);
57 | |
58 | | /**
59 | | * @dev Emitted when operation `id` is cancelled.
60 | | */
61 | | event Cancelled(bytes32 indexed id);
62 | |
63 | | /**
64 | | * @dev Emitted when the minimum delay for future operations is modified.
65 | | */
66 | | event MinDelayChange(uint256 oldDuration, uint256 newDuration);
67 | |
68 | | /**
69 | | * @dev Initializes the contract with the following parameters:
70 | | *
71 | | * - `minDelay`: initial minimum delay for operations
72 | | * - `proposers`: accounts to be granted proposer and canceller roles
73 | | * - `executors`: accounts to be granted executor role
74 | | * - `admin`: optional account to be granted admin role; disable with zero address
75 | | *
76 | | * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
77 | | * without being subject to delay, but this role should be subsequently renounced in favor of
78 | | * administration through timelocked proposals. Previous versions of this contract would assign
79 | | * this admin to the deployer automatically and should be renounced as well.
80 | | */
81 | | constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {
82 | | _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
83 | | _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
84 | | _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
85 | | _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);
86 | |
87 | | // self administration
88 | | _setupRole(TIMELOCK_ADMIN_ROLE, address(this));
89 | |
90 | | // optional admin
91 | | if (admin != address(0)) {
92 | | _setupRole(TIMELOCK_ADMIN_ROLE, admin);
93 | | }
94 | |
95 | | // register proposers and cancellers
96 | | for (uint256 i = 0; i < proposers.length; ++i) {
97 | | _setupRole(PROPOSER_ROLE, proposers[i]);
98 | | _setupRole(CANCELLER_ROLE, proposers[i]);
99 | | }
100 | |
101 | | // register executors
102 | | for (uint256 i = 0; i < executors.length; ++i) {
103 | | _setupRole(EXECUTOR_ROLE, executors[i]);
104 | | }
105 | |
106 | | _minDelay = minDelay;
107 | | emit MinDelayChange(0, minDelay);
108 | | }
109 | |
110 | | /**
111 | | * @dev Modifier to make a function callable only by a certain role. In
112 | | * addition to checking the sender's role, `address(0)` 's role is also
113 | | * considered. Granting a role to `address(0)` is equivalent to enabling
114 | | * this role for everyone.
115 | | */
116 | | modifier onlyRoleOrOpenRole(bytes32 role) {
117 | | if (!hasRole(role, address(0))) {
118 | | _checkRole(role, _msgSender());
119 | | }
120 | | _;
121 | | }
122 | |
123 | | /**
124 | | * @dev Contract might receive/hold ETH as part of the maintenance process.
125 | | */
126 | | receive() external payable {}
127 | |
128 | | /**
129 | | * @dev See {IERC165-supportsInterface}.
130 | | */
131 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {
132 | | return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
133 | | }
134 | |
135 | | /**
136 | | * @dev Returns whether an id correspond to a registered operation. This
137 | | * includes both Pending, Ready and Done operations.
138 | | */
139 | | function isOperation(bytes32 id) public view virtual returns (bool) {
140 | | return getTimestamp(id) > 0;
141 | | }
142 | |
143 | | /**
144 | | * @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
145 | | */
146 | | function isOperationPending(bytes32 id) public view virtual returns (bool) {
147 | | return getTimestamp(id) > _DONE_TIMESTAMP;
148 | | }
149 | |
150 | | /**
151 | | * @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
152 | | */
153 | | function isOperationReady(bytes32 id) public view virtual returns (bool) {
154 | | uint256 timestamp = getTimestamp(id);
155 | | return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
156 | | }
157 | |
158 | | /**
159 | | * @dev Returns whether an operation is done or not.
160 | | */
161 | | function isOperationDone(bytes32 id) public view virtual returns (bool) {
162 | | return getTimestamp(id) == _DONE_TIMESTAMP;
163 | | }
164 | |
165 | | /**
166 | | * @dev Returns the timestamp at which an operation becomes ready (0 for
167 | | * unset operations, 1 for done operations).
168 | | */
169 | | function getTimestamp(bytes32 id) public view virtual returns (uint256) {
170 | | return _timestamps[id];
171 | | }
172 | |
173 | | /**
174 | | * @dev Returns the minimum delay for an operation to become valid.
175 | | *
176 | | * This value can be changed by executing an operation that calls `updateDelay`.
177 | | */
178 | | function getMinDelay() public view virtual returns (uint256) {
179 | | return _minDelay;
180 | | }
181 | |
182 | | /**
183 | | * @dev Returns the identifier of an operation containing a single
184 | | * transaction.
185 | | */
186 | | function hashOperation(
187 | | address target,
188 | | uint256 value,
189 | | bytes calldata data,
190 | | bytes32 predecessor,
191 | | bytes32 salt
192 | | ) public pure virtual returns (bytes32) {
193 | | return keccak256(abi.encode(target, value, data, predecessor, salt));
194 | | }
195 | |
196 | | /**
197 | | * @dev Returns the identifier of an operation containing a batch of
198 | | * transactions.
199 | | */
200 | | function hashOperationBatch(
201 | | address[] calldata targets,
202 | | uint256[] calldata values,
203 | | bytes[] calldata payloads,
204 | | bytes32 predecessor,
205 | | bytes32 salt
206 | | ) public pure virtual returns (bytes32) {
207 | | return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
208 | | }
209 | |
210 | | /**
211 | | * @dev Schedule an operation containing a single transaction.
212 | | *
213 | | * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
214 | | *
215 | | * Requirements:
216 | | *
217 | | * - the caller must have the 'proposer' role.
218 | | */
219 | | function schedule(
220 | | address target,
221 | | uint256 value,
222 | | bytes calldata data,
223 | | bytes32 predecessor,
224 | | bytes32 salt,
225 | | uint256 delay
226 | | ) public virtual onlyRole(PROPOSER_ROLE) {
227 | | bytes32 id = hashOperation(target, value, data, predecessor, salt);
228 | | _schedule(id, delay);
229 | | emit CallScheduled(id, 0, target, value, data, predecessor, delay);
230 | | if (salt != bytes32(0)) {
231 | | emit CallSalt(id, salt);
232 | | }
233 | | }
234 | |
235 | | /**
236 | | * @dev Schedule an operation containing a batch of transactions.
237 | | *
238 | | * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
239 | | *
240 | | * Requirements:
241 | | *
242 | | * - the caller must have the 'proposer' role.
243 | | */
244 | | function scheduleBatch(
245 | | address[] calldata targets,
246 | | uint256[] calldata values,
247 | | bytes[] calldata payloads,
248 | | bytes32 predecessor,
249 | | bytes32 salt,
250 | | uint256 delay
251 | | ) public virtual onlyRole(PROPOSER_ROLE) {
252 | | require(targets.length == values.length, "TimelockController: length mismatch");
253 | | require(targets.length == payloads.length, "TimelockController: length mismatch");
254 | |
255 | | bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
256 | | _schedule(id, delay);
257 | | for (uint256 i = 0; i < targets.length; ++i) {
258 | | emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
259 | | }
260 | | if (salt != bytes32(0)) {
261 | | emit CallSalt(id, salt);
262 | | }
263 | | }
264 | |
265 | | /**
266 | | * @dev Schedule an operation that is to become valid after a given delay.
267 | | */
268 | | function _schedule(bytes32 id, uint256 delay) private {
269 | | require(!isOperation(id), "TimelockController: operation already scheduled");
270 | | require(delay >= getMinDelay(), "TimelockController: insufficient delay");
271 | | _timestamps[id] = block.timestamp + delay;
272 | | }
273 | |
274 | | /**
275 | | * @dev Cancel an operation.
276 | | *
277 | | * Requirements:
278 | | *
279 | | * - the caller must have the 'canceller' role.
280 | | */
281 | | function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
282 | | require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
283 | | delete _timestamps[id];
284 | |
285 | | emit Cancelled(id);
286 | | }
287 | |
288 | | /**
289 | | * @dev Execute an (ready) operation containing a single transaction.
290 | | *
291 | | * Emits a {CallExecuted} event.
292 | | *
293 | | * Requirements:
294 | | *
295 | | * - the caller must have the 'executor' role.
296 | | */
297 | | // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
298 | | // thus any modifications to the operation during reentrancy should be caught.
299 | | // slither-disable-next-line reentrancy-eth
300 | | function execute(
301 | | address target,
302 | | uint256 value,
303 | | bytes calldata payload,
304 | | bytes32 predecessor,
305 | | bytes32 salt
306 | | ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
307 | | bytes32 id = hashOperation(target, value, payload, predecessor, salt);
308 | |
309 | | _beforeCall(id, predecessor);
310 | | _execute(target, value, payload);
311 | | emit CallExecuted(id, 0, target, value, payload);
312 | | _afterCall(id);
313 | | }
314 | |
315 | | /**
316 | | * @dev Execute an (ready) operation containing a batch of transactions.
317 | | *
318 | | * Emits one {CallExecuted} event per transaction in the batch.
319 | | *
320 | | * Requirements:
321 | | *
322 | | * - the caller must have the 'executor' role.
323 | | */
324 | | // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
325 | | // thus any modifications to the operation during reentrancy should be caught.
326 | | // slither-disable-next-line reentrancy-eth
327 | | function executeBatch(
328 | | address[] calldata targets,
329 | | uint256[] calldata values,
330 | | bytes[] calldata payloads,
331 | | bytes32 predecessor,
332 | | bytes32 salt
333 | | ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
334 | | require(targets.length == values.length, "TimelockController: length mismatch");
335 | | require(targets.length == payloads.length, "TimelockController: length mismatch");
336 | |
337 | | bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
338 | |
339 | | _beforeCall(id, predecessor);
340 | | for (uint256 i = 0; i < targets.length; ++i) {
341 | | address target = targets[i];
342 | | uint256 value = values[i];
343 | | bytes calldata payload = payloads[i];
344 | | _execute(target, value, payload);
345 | | emit CallExecuted(id, i, target, value, payload);
346 | | }
347 | | _afterCall(id);
348 | | }
349 | |
350 | | /**
351 | | * @dev Execute an operation's call.
352 | | */
353 | | function _execute(address target, uint256 value, bytes calldata data) internal virtual {
354 | | (bool success, ) = target.call{value: value}(data);
355 | | require(success, "TimelockController: underlying transaction reverted");
356 | | }
357 | |
358 | | /**
359 | | * @dev Checks before execution of an operation's calls.
360 | | */
361 | | function _beforeCall(bytes32 id, bytes32 predecessor) private view {
362 | | require(isOperationReady(id), "TimelockController: operation is not ready");
363 | | require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
364 | | }
365 | |
366 | | /**
367 | | * @dev Checks after execution of an operation's calls.
368 | | */
369 | | function _afterCall(bytes32 id) private {
370 | | require(isOperationReady(id), "TimelockController: operation is not ready");
371 | | _timestamps[id] = _DONE_TIMESTAMP;
372 | | }
373 | |
374 | | /**
375 | | * @dev Changes the minimum timelock duration for future operations.
376 | | *
377 | | * Emits a {MinDelayChange} event.
378 | | *
379 | | * Requirements:
380 | | *
381 | | * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
382 | | * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
383 | | */
384 | | function updateDelay(uint256 newDelay) external virtual {
385 | | require(msg.sender == address(this), "TimelockController: caller must be timelock");
386 | | emit MinDelayChange(_minDelay, newDelay);
387 | | _minDelay = newDelay;
388 | | }
389 | |
390 | | /**
391 | | * @dev See {IERC721Receiver-onERC721Received}.
392 | | */
393 | | function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
394 | | return this.onERC721Received.selector;
395 | | }
396 | |
397 | | /**
398 | | * @dev See {IERC1155Receiver-onERC1155Received}.
399 | | */
400 | | function onERC1155Received(
401 | | address,
402 | | address,
403 | | uint256,
404 | | uint256,
405 | | bytes memory
406 | | ) public virtual override returns (bytes4) {
407 | | return this.onERC1155Received.selector;
408 | | }
409 | |
410 | | /**
411 | | * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
412 | | */
413 | | function onERC1155BatchReceived(
414 | | address,
415 | | address,
416 | | uint256[] memory,
417 | | uint256[] memory,
418 | | bytes memory
419 | | ) public virtual override returns (bytes4) {
420 | | return this.onERC1155BatchReceived.selector;
421 | | }
422 | | }
423 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/compatibility/GovernorCompatibilityBravo.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../../utils/math/SafeCast.sol";
7 | | import "../extensions/IGovernorTimelock.sol";
8 | | import "../Governor.sol";
9 | | import "./IGovernorCompatibilityBravo.sol";
10 | |
11 | | /**
12 | | * @dev Compatibility layer that implements GovernorBravo compatibility on top of {Governor}.
13 | | *
14 | | * This compatibility layer includes a voting system and requires a {IGovernorTimelock} compatible module to be added
15 | | * through inheritance. It does not include token bindings, nor does it include any variable upgrade patterns.
16 | | *
17 | | * NOTE: When using this module, you may need to enable the Solidity optimizer to avoid hitting the contract size limit.
18 | | *
19 | | * _Available since v4.3._
20 | | */
21 | | abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorCompatibilityBravo, Governor {
22 | | enum VoteType {
23 | | Against,
24 | | For,
25 | | Abstain
26 | | }
27 | |
28 | | struct ProposalDetails {
29 | | address proposer;
30 | | address[] targets;
31 | | uint256[] values;
32 | | string[] signatures;
33 | | bytes[] calldatas;
34 | | uint256 forVotes;
35 | | uint256 againstVotes;
36 | | uint256 abstainVotes;
37 | | mapping(address => Receipt) receipts;
38 | | bytes32 descriptionHash;
39 | | }
40 | |
41 | | mapping(uint256 => ProposalDetails) private _proposalDetails;
42 | |
43 | | // solhint-disable-next-line func-name-mixedcase
44 | | function COUNTING_MODE() public pure virtual override returns (string memory) {
45 | | return "support=bravo&quorum=bravo";
46 | | }
47 | |
48 | | // ============================================== Proposal lifecycle ==============================================
49 | | /**
50 | | * @dev See {IGovernor-propose}.
51 | | */
52 | | function propose(
53 | | address[] memory targets,
54 | | uint256[] memory values,
55 | | bytes[] memory calldatas,
56 | | string memory description
57 | | ) public virtual override(IGovernor, Governor) returns (uint256) {
58 | | // Stores the proposal details (if not already present) and executes the propose logic from the core.
59 | | _storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description);
60 | | return super.propose(targets, values, calldatas, description);
61 | | }
62 | |
63 | | /**
64 | | * @dev See {IGovernorCompatibilityBravo-propose}.
65 | | */
66 | | function propose(
67 | | address[] memory targets,
68 | | uint256[] memory values,
69 | | string[] memory signatures,
70 | | bytes[] memory calldatas,
71 | | string memory description
72 | | ) public virtual override returns (uint256) {
73 | | require(signatures.length == calldatas.length, "GovernorBravo: invalid signatures length");
74 | | // Stores the full proposal and fallback to the public (possibly overridden) propose. The fallback is done
75 | | // after the full proposal is stored, so the store operation included in the fallback will be skipped. Here we
76 | | // call `propose` and not `super.propose` to make sure if a child contract override `propose`, whatever code
77 | | // is added there is also executed when calling this alternative interface.
78 | | _storeProposal(_msgSender(), targets, values, signatures, calldatas, description);
79 | | return propose(targets, values, _encodeCalldata(signatures, calldatas), description);
80 | | }
81 | |
82 | | /**
83 | | * @dev See {IGovernorCompatibilityBravo-queue}.
84 | | */
85 | | function queue(uint256 proposalId) public virtual override {
86 | | (
87 | | address[] memory targets,
88 | | uint256[] memory values,
89 | | bytes[] memory calldatas,
90 | | bytes32 descriptionHash
91 | | ) = _getProposalParameters(proposalId);
92 | |
93 | | queue(targets, values, calldatas, descriptionHash);
94 | | }
95 | |
96 | | /**
97 | | * @dev See {IGovernorCompatibilityBravo-execute}.
98 | | */
99 | | function execute(uint256 proposalId) public payable virtual override {
100 | | (
101 | | address[] memory targets,
102 | | uint256[] memory values,
103 | | bytes[] memory calldatas,
104 | | bytes32 descriptionHash
105 | | ) = _getProposalParameters(proposalId);
106 | |
107 | | execute(targets, values, calldatas, descriptionHash);
108 | | }
109 | |
110 | | /**
111 | | * @dev Cancel a proposal with GovernorBravo logic.
112 | | */
113 | | function cancel(uint256 proposalId) public virtual override {
114 | | (
115 | | address[] memory targets,
116 | | uint256[] memory values,
117 | | bytes[] memory calldatas,
118 | | bytes32 descriptionHash
119 | | ) = _getProposalParameters(proposalId);
120 | |
121 | | cancel(targets, values, calldatas, descriptionHash);
122 | | }
123 | |
124 | | /**
125 | | * @dev Cancel a proposal with GovernorBravo logic. At any moment a proposal can be cancelled, either by the
126 | | * proposer, or by third parties if the proposer's voting power has dropped below the proposal threshold.
127 | | */
128 | | function cancel(
129 | | address[] memory targets,
130 | | uint256[] memory values,
131 | | bytes[] memory calldatas,
132 | | bytes32 descriptionHash
133 | | ) public virtual override(IGovernor, Governor) returns (uint256) {
134 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
135 | | address proposer = _proposalDetails[proposalId].proposer;
136 | |
137 | | require(
138 | | _msgSender() == proposer || getVotes(proposer, clock() - 1) < proposalThreshold(),
139 | | "GovernorBravo: proposer above threshold"
140 | | );
141 | |
142 | | return _cancel(targets, values, calldatas, descriptionHash);
143 | | }
144 | |
145 | | /**
146 | | * @dev Encodes calldatas with optional function signature.
147 | | */
148 | | function _encodeCalldata(
149 | | string[] memory signatures,
150 | | bytes[] memory calldatas
151 | | ) private pure returns (bytes[] memory) {
152 | | bytes[] memory fullcalldatas = new bytes[](calldatas.length);
153 | | for (uint256 i = 0; i < fullcalldatas.length; ++i) {
154 | | fullcalldatas[i] = bytes(signatures[i]).length == 0
155 | | ? calldatas[i]
156 | | : abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]);
157 | | }
158 | |
159 | | return fullcalldatas;
160 | | }
161 | |
162 | | /**
163 | | * @dev Retrieve proposal parameters by id, with fully encoded calldatas.
164 | | */
165 | | function _getProposalParameters(
166 | | uint256 proposalId
167 | | )
168 | | private
169 | | view
170 | | returns (address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
171 | | {
172 | | ProposalDetails storage details = _proposalDetails[proposalId];
173 | | return (
174 | | details.targets,
175 | | details.values,
176 | | _encodeCalldata(details.signatures, details.calldatas),
177 | | details.descriptionHash
178 | | );
179 | | }
180 | |
181 | | /**
182 | | * @dev Store proposal metadata (if not already present) for later lookup.
183 | | */
184 | | function _storeProposal(
185 | | address proposer,
186 | | address[] memory targets,
187 | | uint256[] memory values,
188 | | string[] memory signatures,
189 | | bytes[] memory calldatas,
190 | | string memory description
191 | | ) private {
192 | | bytes32 descriptionHash = keccak256(bytes(description));
193 | | uint256 proposalId = hashProposal(targets, values, _encodeCalldata(signatures, calldatas), descriptionHash);
194 | |
195 | | ProposalDetails storage details = _proposalDetails[proposalId];
196 | | if (details.descriptionHash == bytes32(0)) {
197 | | details.proposer = proposer;
198 | | details.targets = targets;
199 | | details.values = values;
200 | | details.signatures = signatures;
201 | | details.calldatas = calldatas;
202 | | details.descriptionHash = descriptionHash;
203 | | }
204 | | }
205 | |
206 | | // ==================================================== Views =====================================================
207 | | /**
208 | | * @dev See {IGovernorCompatibilityBravo-proposals}.
209 | | */
210 | | function proposals(
211 | | uint256 proposalId
212 | | )
213 | | public
214 | | view
215 | | virtual
216 | | override
217 | | returns (
218 | | uint256 id,
219 | | address proposer,
220 | | uint256 eta,
221 | | uint256 startBlock,
222 | | uint256 endBlock,
223 | | uint256 forVotes,
224 | | uint256 againstVotes,
225 | | uint256 abstainVotes,
226 | | bool canceled,
227 | | bool executed
228 | | )
229 | | {
230 | | id = proposalId;
231 | | eta = proposalEta(proposalId);
232 | | startBlock = proposalSnapshot(proposalId);
233 | | endBlock = proposalDeadline(proposalId);
234 | |
235 | | ProposalDetails storage details = _proposalDetails[proposalId];
236 | | proposer = details.proposer;
237 | | forVotes = details.forVotes;
238 | | againstVotes = details.againstVotes;
239 | | abstainVotes = details.abstainVotes;
240 | |
241 | | ProposalState currentState = state(proposalId);
242 | | canceled = currentState == ProposalState.Canceled;
243 | | executed = currentState == ProposalState.Executed;
244 | | }
245 | |
246 | | /**
247 | | * @dev See {IGovernorCompatibilityBravo-getActions}.
248 | | */
249 | | function getActions(
250 | | uint256 proposalId
251 | | )
252 | | public
253 | | view
254 | | virtual
255 | | override
256 | | returns (
257 | | address[] memory targets,
258 | | uint256[] memory values,
259 | | string[] memory signatures,
260 | | bytes[] memory calldatas
261 | | )
262 | | {
263 | | ProposalDetails storage details = _proposalDetails[proposalId];
264 | | return (details.targets, details.values, details.signatures, details.calldatas);
265 | | }
266 | |
267 | | /**
268 | | * @dev See {IGovernorCompatibilityBravo-getReceipt}.
269 | | */
270 | | function getReceipt(uint256 proposalId, address voter) public view virtual override returns (Receipt memory) {
271 | | return _proposalDetails[proposalId].receipts[voter];
272 | | }
273 | |
274 | | /**
275 | | * @dev See {IGovernorCompatibilityBravo-quorumVotes}.
276 | | */
277 | | function quorumVotes() public view virtual override returns (uint256) {
278 | | return quorum(clock() - 1);
279 | | }
280 | |
281 | | // ==================================================== Voting ====================================================
282 | | /**
283 | | * @dev See {IGovernor-hasVoted}.
284 | | */
285 | | function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
286 | | return _proposalDetails[proposalId].receipts[account].hasVoted;
287 | | }
288 | |
289 | | /**
290 | | * @dev See {Governor-_quorumReached}. In this module, only forVotes count toward the quorum.
291 | | */
292 | | function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
293 | | ProposalDetails storage details = _proposalDetails[proposalId];
294 | | return quorum(proposalSnapshot(proposalId)) <= details.forVotes;
295 | | }
296 | |
297 | | /**
298 | | * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
299 | | */
300 | | function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
301 | | ProposalDetails storage details = _proposalDetails[proposalId];
302 | | return details.forVotes > details.againstVotes;
303 | | }
304 | |
305 | | /**
306 | | * @dev See {Governor-_countVote}. In this module, the support follows Governor Bravo.
307 | | */
308 | | function _countVote(
309 | | uint256 proposalId,
310 | | address account,
311 | | uint8 support,
312 | | uint256 weight,
313 | | bytes memory // params
314 | | ) internal virtual override {
315 | | ProposalDetails storage details = _proposalDetails[proposalId];
316 | | Receipt storage receipt = details.receipts[account];
317 | |
318 | | require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already cast");
319 | | receipt.hasVoted = true;
320 | | receipt.support = support;
321 | | receipt.votes = SafeCast.toUint96(weight);
322 | |
323 | | if (support == uint8(VoteType.Against)) {
324 | | details.againstVotes += weight;
325 | | } else if (support == uint8(VoteType.For)) {
326 | | details.forVotes += weight;
327 | | } else if (support == uint8(VoteType.Abstain)) {
328 | | details.abstainVotes += weight;
329 | | } else {
330 | | revert("GovernorCompatibilityBravo: invalid vote type");
331 | | }
332 | | }
333 | | }
334 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/compatibility/IGovernorCompatibilityBravo.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/compatibility/IGovernorCompatibilityBravo.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../IGovernor.sol";
7 | |
8 | | /**
9 | | * @dev Interface extension that adds missing functions to the {Governor} core to provide `GovernorBravo` compatibility.
10 | | *
11 | | * _Available since v4.3._
12 | | */
13 | | abstract contract IGovernorCompatibilityBravo is IGovernor {
14 | | /**
15 | | * @dev Proposal structure from Compound Governor Bravo. Not actually used by the compatibility layer, as
16 | | * {{proposal}} returns a very different structure.
17 | | */
18 | | struct Proposal {
19 | | uint256 id;
20 | | address proposer;
21 | | uint256 eta;
22 | | address[] targets;
23 | | uint256[] values;
24 | | string[] signatures;
25 | | bytes[] calldatas;
26 | | uint256 startBlock;
27 | | uint256 endBlock;
28 | | uint256 forVotes;
29 | | uint256 againstVotes;
30 | | uint256 abstainVotes;
31 | | bool canceled;
32 | | bool executed;
33 | | mapping(address => Receipt) receipts;
34 | | }
35 | |
36 | | /**
37 | | * @dev Receipt structure from Compound Governor Bravo
38 | | */
39 | | struct Receipt {
40 | | bool hasVoted;
41 | | uint8 support;
42 | | uint96 votes;
43 | | }
44 | |
45 | | /**
46 | | * @dev Part of the Governor Bravo's interface.
47 | | */
48 | | function quorumVotes() public view virtual returns (uint256);
49 | |
50 | | /**
51 | | * @dev Part of the Governor Bravo's interface: _"The official record of all proposals ever proposed"_.
52 | | */
53 | | function proposals(
54 | | uint256
55 | | )
56 | | public
57 | | view
58 | | virtual
59 | | returns (
60 | | uint256 id,
61 | | address proposer,
62 | | uint256 eta,
63 | | uint256 startBlock,
64 | | uint256 endBlock,
65 | | uint256 forVotes,
66 | | uint256 againstVotes,
67 | | uint256 abstainVotes,
68 | | bool canceled,
69 | | bool executed
70 | | );
71 | |
72 | | /**
73 | | * @dev Part of the Governor Bravo's interface: _"Function used to propose a new proposal"_.
74 | | */
75 | | function propose(
76 | | address[] memory targets,
77 | | uint256[] memory values,
78 | | string[] memory signatures,
79 | | bytes[] memory calldatas,
80 | | string memory description
81 | | ) public virtual returns (uint256);
82 | |
83 | | /**
84 | | * @dev Part of the Governor Bravo's interface: _"Queues a proposal of state succeeded"_.
85 | | */
86 | | function queue(uint256 proposalId) public virtual;
87 | |
88 | | /**
89 | | * @dev Part of the Governor Bravo's interface: _"Executes a queued proposal if eta has passed"_.
90 | | */
91 | | function execute(uint256 proposalId) public payable virtual;
92 | |
93 | | /**
94 | | * @dev Cancels a proposal only if the sender is the proposer or the proposer delegates' voting power dropped below the proposal threshold.
95 | | */
96 | | function cancel(uint256 proposalId) public virtual;
97 | |
98 | | /**
99 | | * @dev Part of the Governor Bravo's interface: _"Gets actions of a proposal"_.
100 | | */
101 | | function getActions(
102 | | uint256 proposalId
103 | | )
104 | | public
105 | | view
106 | | virtual
107 | | returns (
108 | | address[] memory targets,
109 | | uint256[] memory values,
110 | | string[] memory signatures,
111 | | bytes[] memory calldatas
112 | | );
113 | |
114 | | /**
115 | | * @dev Part of the Governor Bravo's interface: _"Gets the receipt for a voter on a given proposal"_.
116 | | */
117 | | function getReceipt(uint256 proposalId, address voter) public view virtual returns (Receipt memory);
118 | | }
119 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorSettings.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorSettings.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../Governor.sol";
7 | |
8 | | /**
9 | | * @dev Extension of {Governor} for settings updatable through governance.
10 | | *
11 | | * _Available since v4.4._
12 | | */
13 | | abstract contract GovernorSettings is Governor {
14 | | uint256 private _votingDelay;
15 | | uint256 private _votingPeriod;
16 | | uint256 private _proposalThreshold;
17 | |
18 | | event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
19 | | event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
20 | | event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);
21 | |
22 | | /**
23 | | * @dev Initialize the governance parameters.
24 | | */
25 | | constructor(uint256 initialVotingDelay, uint256 initialVotingPeriod, uint256 initialProposalThreshold) {
26 | | _setVotingDelay(initialVotingDelay);
27 | | _setVotingPeriod(initialVotingPeriod);
28 | | _setProposalThreshold(initialProposalThreshold);
29 | | }
30 | |
31 | | /**
32 | | * @dev See {IGovernor-votingDelay}.
33 | | */
34 | | function votingDelay() public view virtual override returns (uint256) {
35 | | return _votingDelay;
36 | | }
37 | |
38 | | /**
39 | | * @dev See {IGovernor-votingPeriod}.
40 | | */
41 | | function votingPeriod() public view virtual override returns (uint256) {
42 | | return _votingPeriod;
43 | | }
44 | |
45 | | /**
46 | | * @dev See {Governor-proposalThreshold}.
47 | | */
48 | | function proposalThreshold() public view virtual override returns (uint256) {
49 | | return _proposalThreshold;
50 | | }
51 | |
52 | | /**
53 | | * @dev Update the voting delay. This operation can only be performed through a governance proposal.
54 | | *
55 | | * Emits a {VotingDelaySet} event.
56 | | */
57 | | function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance {
58 | | _setVotingDelay(newVotingDelay);
59 | | }
60 | |
61 | | /**
62 | | * @dev Update the voting period. This operation can only be performed through a governance proposal.
63 | | *
64 | | * Emits a {VotingPeriodSet} event.
65 | | */
66 | | function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance {
67 | | _setVotingPeriod(newVotingPeriod);
68 | | }
69 | |
70 | | /**
71 | | * @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
72 | | *
73 | | * Emits a {ProposalThresholdSet} event.
74 | | */
75 | | function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
76 | | _setProposalThreshold(newProposalThreshold);
77 | | }
78 | |
79 | | /**
80 | | * @dev Internal setter for the voting delay.
81 | | *
82 | | * Emits a {VotingDelaySet} event.
83 | | */
84 | | function _setVotingDelay(uint256 newVotingDelay) internal virtual {
85 | | emit VotingDelaySet(_votingDelay, newVotingDelay);
86 | | _votingDelay = newVotingDelay;
87 | | }
88 | |
89 | | /**
90 | | * @dev Internal setter for the voting period.
91 | | *
92 | | * Emits a {VotingPeriodSet} event.
93 | | */
94 | | function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
95 | | // voting period must be at least one block long
96 | | require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
97 | | emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
98 | | _votingPeriod = newVotingPeriod;
99 | | }
100 | |
101 | | /**
102 | | * @dev Internal setter for the proposal threshold.
103 | | *
104 | | * Emits a {ProposalThresholdSet} event.
105 | | */
106 | | function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
107 | | emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
108 | | _proposalThreshold = newProposalThreshold;
109 | | }
110 | | }
111 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorTimelockControl.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./IGovernorTimelock.sol";
7 | | import "../Governor.sol";
8 | | import "../TimelockController.sol";
9 | |
10 | | /**
11 | | * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a
12 | | * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The
13 | | * {Governor} needs the proposer (and ideally the executor) roles for the {Governor} to work properly.
14 | | *
15 | | * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
16 | | * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
17 | | * inaccessible.
18 | | *
19 | | * WARNING: Setting up the TimelockController to have additional proposers besides the governor is very risky, as it
20 | | * grants them powers that they must be trusted or known not to use: 1) {onlyGovernance} functions like {relay} are
21 | | * available to them through the timelock, and 2) approved governance proposals can be blocked by them, effectively
22 | | * executing a Denial of Service attack. This risk will be mitigated in a future release.
23 | | *
24 | | * _Available since v4.3._
25 | | */
26 | | abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
27 | | TimelockController private _timelock;
28 | | mapping(uint256 => bytes32) private _timelockIds;
29 | |
30 | | /**
31 | | * @dev Emitted when the timelock controller used for proposal execution is modified.
32 | | */
33 | | event TimelockChange(address oldTimelock, address newTimelock);
34 | |
35 | | /**
36 | | * @dev Set the timelock.
37 | | */
38 | | constructor(TimelockController timelockAddress) {
39 | | _updateTimelock(timelockAddress);
40 | | }
41 | |
42 | | /**
43 | | * @dev See {IERC165-supportsInterface}.
44 | | */
45 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) {
46 | | return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId);
47 | | }
48 | |
49 | | /**
50 | | * @dev Overridden version of the {Governor-state} function with added support for the `Queued` state.
51 | | */
52 | | function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
53 | | ProposalState currentState = super.state(proposalId);
54 | |
55 | | if (currentState != ProposalState.Succeeded) {
56 | | return currentState;
57 | | }
58 | |
59 | | // core tracks execution, so we just have to check if successful proposal have been queued.
60 | | bytes32 queueid = _timelockIds[proposalId];
61 | | if (queueid == bytes32(0)) {
62 | | return currentState;
63 | | } else if (_timelock.isOperationDone(queueid)) {
64 | | return ProposalState.Executed;
65 | | } else if (_timelock.isOperationPending(queueid)) {
66 | | return ProposalState.Queued;
67 | | } else {
68 | | return ProposalState.Canceled;
69 | | }
70 | | }
71 | |
72 | | /**
73 | | * @dev Public accessor to check the address of the timelock
74 | | */
75 | | function timelock() public view virtual override returns (address) {
76 | | return address(_timelock);
77 | | }
78 | |
79 | | /**
80 | | * @dev Public accessor to check the eta of a queued proposal
81 | | */
82 | | function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
83 | | uint256 eta = _timelock.getTimestamp(_timelockIds[proposalId]);
84 | | return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value
85 | | }
86 | |
87 | | /**
88 | | * @dev Function to queue a proposal to the timelock.
89 | | */
90 | | function queue(
91 | | address[] memory targets,
92 | | uint256[] memory values,
93 | | bytes[] memory calldatas,
94 | | bytes32 descriptionHash
95 | | ) public virtual override returns (uint256) {
96 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
97 | |
98 | | require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful");
99 | |
100 | | uint256 delay = _timelock.getMinDelay();
101 | | _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
102 | | _timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);
103 | |
104 | | emit ProposalQueued(proposalId, block.timestamp + delay);
105 | |
106 | | return proposalId;
107 | | }
108 | |
109 | | /**
110 | | * @dev Overridden execute function that run the already queued proposal through the timelock.
111 | | */
112 | | function _execute(
113 | | uint256 /* proposalId */,
114 | | address[] memory targets,
115 | | uint256[] memory values,
116 | | bytes[] memory calldatas,
117 | | bytes32 descriptionHash
118 | | ) internal virtual override {
119 | | _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
120 | | }
121 | |
122 | | /**
123 | | * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
124 | | * been queued.
125 | | */
126 | | // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
127 | | // well behaved (according to TimelockController) and this will not happen.
128 | | // slither-disable-next-line reentrancy-no-eth
129 | | function _cancel(
130 | | address[] memory targets,
131 | | uint256[] memory values,
132 | | bytes[] memory calldatas,
133 | | bytes32 descriptionHash
134 | | ) internal virtual override returns (uint256) {
135 | | uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
136 | |
137 | | if (_timelockIds[proposalId] != 0) {
138 | | _timelock.cancel(_timelockIds[proposalId]);
139 | | delete _timelockIds[proposalId];
140 | | }
141 | |
142 | | return proposalId;
143 | | }
144 | |
145 | | /**
146 | | * @dev Address through which the governor executes action. In this case, the timelock.
147 | | */
148 | | function _executor() internal view virtual override returns (address) {
149 | | return address(_timelock);
150 | | }
151 | |
152 | | /**
153 | | * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
154 | | * must be proposed, scheduled, and executed through governance proposals.
155 | | *
156 | | * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
157 | | */
158 | | function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
159 | | _updateTimelock(newTimelock);
160 | | }
161 | |
162 | | function _updateTimelock(TimelockController newTimelock) private {
163 | | emit TimelockChange(address(_timelock), address(newTimelock));
164 | | _timelock = newTimelock;
165 | | }
166 | | }
167 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotes.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorVotes.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../Governor.sol";
7 | | import "../../interfaces/IERC5805.sol";
8 | |
9 | | /**
10 | | * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.
11 | | *
12 | | * _Available since v4.3._
13 | | */
14 | | abstract contract GovernorVotes is Governor {
15 | | IERC5805 public immutable token;
16 | |
17 | | constructor(IVotes tokenAddress) {
18 | | token = IERC5805(address(tokenAddress));
19 | | }
20 | |
21 | | /**
22 | | * @dev Clock (as specified in EIP-6372) is set to match the token's clock. Fallback to block numbers if the token
23 | | * does not implement EIP-6372.
24 | | */
25 | | function clock() public view virtual override returns (uint48) {
26 | | try token.clock() returns (uint48 timepoint) {
27 | | return timepoint;
28 | | } catch {
29 | | return SafeCast.toUint48(block.number);
30 | | }
31 | | }
32 | |
33 | | /**
34 | | * @dev Machine-readable description of the clock as specified in EIP-6372.
35 | | */
36 | | // solhint-disable-next-line func-name-mixedcase
37 | | function CLOCK_MODE() public view virtual override returns (string memory) {
38 | | try token.CLOCK_MODE() returns (string memory clockmode) {
39 | | return clockmode;
40 | | } catch {
41 | | return "mode=blocknumber&from=default";
42 | | }
43 | | }
44 | |
45 | | /**
46 | | * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
47 | | */
48 | | function _getVotes(
49 | | address account,
50 | | uint256 timepoint,
51 | | bytes memory /*params*/
52 | | ) internal view virtual override returns (uint256) {
53 | | return token.getPastVotes(account, timepoint);
54 | | }
55 | | }
56 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./GovernorVotes.sol";
7 | | import "../../utils/Checkpoints.sol";
8 | | import "../../utils/math/SafeCast.sol";
9 | |
10 | | /**
11 | | * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a
12 | | * fraction of the total supply.
13 | | *
14 | | * _Available since v4.3._
15 | | */
16 | | abstract contract GovernorVotesQuorumFraction is GovernorVotes {
17 | | using Checkpoints for Checkpoints.Trace224;
18 | |
19 | | uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory
20 | |
21 | | /// @custom:oz-retyped-from Checkpoints.History
22 | | Checkpoints.Trace224 private _quorumNumeratorHistory;
23 | |
24 | | event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);
25 | |
26 | | /**
27 | | * @dev Initialize quorum as a fraction of the token's total supply.
28 | | *
29 | | * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is
30 | | * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be
31 | | * customized by overriding {quorumDenominator}.
32 | | */
33 | | constructor(uint256 quorumNumeratorValue) {
34 | | _updateQuorumNumerator(quorumNumeratorValue);
35 | | }
36 | |
37 | | /**
38 | | * @dev Returns the current quorum numerator. See {quorumDenominator}.
39 | | */
40 | | function quorumNumerator() public view virtual returns (uint256) {
41 | | return _quorumNumeratorHistory._checkpoints.length == 0 ? _quorumNumerator : _quorumNumeratorHistory.latest();
42 | | }
43 | |
44 | | /**
45 | | * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
46 | | */
47 | | function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
48 | | // If history is empty, fallback to old storage
49 | | uint256 length = _quorumNumeratorHistory._checkpoints.length;
50 | | if (length == 0) {
51 | | return _quorumNumerator;
52 | | }
53 | |
54 | | // Optimistic search, check the latest checkpoint
55 | | Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1];
56 | | if (latest._key <= timepoint) {
57 | | return latest._value;
58 | | }
59 | |
60 | | // Otherwise, do the binary search
61 | | return _quorumNumeratorHistory.upperLookupRecent(SafeCast.toUint32(timepoint));
62 | | }
63 | |
64 | | /**
65 | | * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.
66 | | */
67 | | function quorumDenominator() public view virtual returns (uint256) {
68 | | return 100;
69 | | }
70 | |
71 | | /**
72 | | * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
73 | | */
74 | | function quorum(uint256 timepoint) public view virtual override returns (uint256) {
75 | | return (token.getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator();
76 | | }
77 | |
78 | | /**
79 | | * @dev Changes the quorum numerator.
80 | | *
81 | | * Emits a {QuorumNumeratorUpdated} event.
82 | | *
83 | | * Requirements:
84 | | *
85 | | * - Must be called through a governance proposal.
86 | | * - New numerator must be smaller or equal to the denominator.
87 | | */
88 | | function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {
89 | | _updateQuorumNumerator(newQuorumNumerator);
90 | | }
91 | |
92 | | /**
93 | | * @dev Changes the quorum numerator.
94 | | *
95 | | * Emits a {QuorumNumeratorUpdated} event.
96 | | *
97 | | * Requirements:
98 | | *
99 | | * - New numerator must be smaller or equal to the denominator.
100 | | */
101 | | function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {
102 | | require(
103 | | newQuorumNumerator <= quorumDenominator(),
104 | | "GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator"
105 | | );
106 | |
107 | | uint256 oldQuorumNumerator = quorumNumerator();
108 | |
109 | | // Make sure we keep track of the original numerator in contracts upgraded from a version without checkpoints.
110 | | if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) {
111 | | _quorumNumeratorHistory._checkpoints.push(
112 | | Checkpoints.Checkpoint224({_key: 0, _value: SafeCast.toUint224(oldQuorumNumerator)})
113 | | );
114 | | }
115 | |
116 | | // Set new quorum for future proposals
117 | | _quorumNumeratorHistory.push(SafeCast.toUint32(clock()), SafeCast.toUint224(newQuorumNumerator));
118 | |
119 | | emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
120 | | }
121 | | }
122 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/IGovernorTimelock.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (governance/extensions/IGovernorTimelock.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../IGovernor.sol";
7 | |
8 | | /**
9 | | * @dev Extension of the {IGovernor} for timelock supporting modules.
10 | | *
11 | | * _Available since v4.3._
12 | | */
13 | | abstract contract IGovernorTimelock is IGovernor {
14 | | event ProposalQueued(uint256 proposalId, uint256 eta);
15 | |
16 | | function timelock() public view virtual returns (address);
17 | |
18 | | function proposalEta(uint256 proposalId) public view virtual returns (uint256);
19 | |
20 | | function queue(
21 | | address[] memory targets,
22 | | uint256[] memory values,
23 | | bytes[] memory calldatas,
24 | | bytes32 descriptionHash
25 | | ) public virtual returns (uint256 proposalId);
26 | | }
27 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
7 | | *
8 | | * _Available since v4.5._
9 | | */
10 | | interface IVotes {
11 | | /**
12 | | * @dev Emitted when an account changes their delegate.
13 | | */
14 | | event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
15 | |
16 | | /**
17 | | * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
18 | | */
19 | | event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
20 | |
21 | | /**
22 | | * @dev Returns the current amount of votes that `account` has.
23 | | */
24 | | function getVotes(address account) external view returns (uint256);
25 | |
26 | | /**
27 | | * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
28 | | * configured to use block numbers, this will return the value at the end of the corresponding block.
29 | | */
30 | | function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
31 | |
32 | | /**
33 | | * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
34 | | * configured to use block numbers, this will return the value at the end of the corresponding block.
35 | | *
36 | | * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
37 | | * Votes that have not been delegated are still part of total supply, even though they would not participate in a
38 | | * vote.
39 | | */
40 | | function getPastTotalSupply(uint256 timepoint) external view returns (uint256);
41 | |
42 | | /**
43 | | * @dev Returns the delegate that `account` has chosen.
44 | | */
45 | | function delegates(address account) external view returns (address);
46 | |
47 | | /**
48 | | * @dev Delegates votes from the sender to `delegatee`.
49 | | */
50 | | function delegate(address delegatee) external;
51 | |
52 | | /**
53 | | * @dev Delegates votes from signer to `delegatee`.
54 | | */
55 | | function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
56 | | }
57 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC165.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../utils/introspection/IERC165.sol";
7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC1967.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
8 | | *
9 | | * _Available since v4.8.3._
10 | | */
11 | | interface IERC1967 {
12 | | /**
13 | | * @dev Emitted when the implementation is upgraded.
14 | | */
15 | | event Upgraded(address indexed implementation);
16 | |
17 | | /**
18 | | * @dev Emitted when the admin account has changed.
19 | | */
20 | | event AdminChanged(address previousAdmin, address newAdmin);
21 | |
22 | | /**
23 | | * @dev Emitted when the beacon is changed.
24 | | */
25 | | event BeaconUpgraded(address indexed beacon);
26 | | }
27 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | interface IERC5267 {
7 | | /**
8 | | * @dev MAY be emitted to signal that the domain could have changed.
9 | | */
10 | | event EIP712DomainChanged();
11 | |
12 | | /**
13 | | * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
14 | | * signature.
15 | | */
16 | | function eip712Domain()
17 | | external
18 | | view
19 | | returns (
20 | | bytes1 fields,
21 | | string memory name,
22 | | string memory version,
23 | | uint256 chainId,
24 | | address verifyingContract,
25 | | bytes32 salt,
26 | | uint256[] memory extensions
27 | | );
28 | | }
29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../governance/utils/IVotes.sol";
7 | | import "./IERC6372.sol";
8 | |
9 | | interface IERC5805 is IERC6372, IVotes {}
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | interface IERC6372 {
7 | | /**
8 | | * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
9 | | */
10 | | function clock() external view returns (uint48);
11 | |
12 | | /**
13 | | * @dev Description of the clock
14 | | */
15 | | // solhint-disable-next-line func-name-mixedcase
16 | | function CLOCK_MODE() external view returns (string memory);
17 | | }
18 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
8 | | * proxy whose upgrades are fully controlled by the current implementation.
9 | | */
10 | | interface IERC1822Proxiable {
11 | | /**
12 | | * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
13 | | * address.
14 | | *
15 | | * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
16 | | * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
17 | | * function revert if invoked through a proxy.
18 | | */
19 | | function proxiableUUID() external view returns (bytes32);
20 | | }
21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../Proxy.sol";
7 | | import "./ERC1967Upgrade.sol";
8 | |
9 | | /**
10 | | * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
11 | | * implementation address that can be changed. This address is stored in storage in the location specified by
12 | | * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
13 | | * implementation behind the proxy.
14 | | */
15 | | contract ERC1967Proxy is Proxy, ERC1967Upgrade {
16 | | /**
17 | | * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
18 | | *
19 | | * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
20 | | * function call, and allows initializing the storage of the proxy like a Solidity constructor.
21 | | */
22 | | constructor(address _logic, bytes memory _data) payable {
23 | | _upgradeToAndCall(_logic, _data, false);
24 | | }
25 | |
26 | | /**
27 | | * @dev Returns the current implementation address.
28 | | */
29 | * | function _implementation() internal view virtual override returns (address impl) {
30 | * | return ERC1967Upgrade._getImplementation();
31 | | }
32 | | }
33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
3 | |
4 | | pragma solidity ^0.8.2;
5 | |
6 | | import "../beacon/IBeacon.sol";
7 | | import "../../interfaces/IERC1967.sol";
8 | | import "../../interfaces/draft-IERC1822.sol";
9 | | import "../../utils/Address.sol";
10 | | import "../../utils/StorageSlot.sol";
11 | |
12 | | /**
13 | | * @dev This abstract contract provides getters and event emitting update functions for
14 | | * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
15 | | *
16 | | * _Available since v4.1._
17 | | */
18 | | abstract contract ERC1967Upgrade is IERC1967 {
19 | | // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
20 | | bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
21 | |
22 | | /**
23 | | * @dev Storage slot with the address of the current implementation.
24 | | * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
25 | | * validated in the constructor.
26 | | */
27 | * | bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
28 | |
29 | | /**
30 | | * @dev Returns the current implementation address.
31 | | */
32 | * | function _getImplementation() internal view returns (address) {
33 | * | return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
34 | | }
35 | |
36 | | /**
37 | | * @dev Stores a new address in the EIP1967 implementation slot.
38 | | */
39 | | function _setImplementation(address newImplementation) private {
40 | | require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
41 | | StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
42 | | }
43 | |
44 | | /**
45 | | * @dev Perform implementation upgrade
46 | | *
47 | | * Emits an {Upgraded} event.
48 | | */
49 | | function _upgradeTo(address newImplementation) internal {
50 | | _setImplementation(newImplementation);
51 | | emit Upgraded(newImplementation);
52 | | }
53 | |
54 | | /**
55 | | * @dev Perform implementation upgrade with additional setup call.
56 | | *
57 | | * Emits an {Upgraded} event.
58 | | */
59 | | function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
60 | | _upgradeTo(newImplementation);
61 | | if (data.length > 0 || forceCall) {
62 | | Address.functionDelegateCall(newImplementation, data);
63 | | }
64 | | }
65 | |
66 | | /**
67 | | * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
68 | | *
69 | | * Emits an {Upgraded} event.
70 | | */
71 | | function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
72 | | // Upgrades from old implementations will perform a rollback test. This test requires the new
73 | | // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
74 | | // this special case will break upgrade paths from old UUPS implementation to new ones.
75 | | if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
76 | | _setImplementation(newImplementation);
77 | | } else {
78 | | try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
79 | | require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
80 | | } catch {
81 | | revert("ERC1967Upgrade: new implementation is not UUPS");
82 | | }
83 | | _upgradeToAndCall(newImplementation, data, forceCall);
84 | | }
85 | | }
86 | |
87 | | /**
88 | | * @dev Storage slot with the admin of the contract.
89 | | * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
90 | | * validated in the constructor.
91 | | */
92 | * | bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
93 | |
94 | | /**
95 | | * @dev Returns the current admin.
96 | | */
97 | * | function _getAdmin() internal view returns (address) {
98 | * | return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
99 | | }
100 | |
101 | | /**
102 | | * @dev Stores a new address in the EIP1967 admin slot.
103 | | */
104 | | function _setAdmin(address newAdmin) private {
105 | | require(newAdmin != address(0), "ERC1967: new admin is the zero address");
106 | | StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
107 | | }
108 | |
109 | | /**
110 | | * @dev Changes the admin of the proxy.
111 | | *
112 | | * Emits an {AdminChanged} event.
113 | | */
114 | | function _changeAdmin(address newAdmin) internal {
115 | | emit AdminChanged(_getAdmin(), newAdmin);
116 | | _setAdmin(newAdmin);
117 | | }
118 | |
119 | | /**
120 | | * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
121 | | * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
122 | | */
123 | | bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
124 | |
125 | | /**
126 | | * @dev Returns the current beacon.
127 | | */
128 | | function _getBeacon() internal view returns (address) {
129 | | return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
130 | | }
131 | |
132 | | /**
133 | | * @dev Stores a new beacon in the EIP1967 beacon slot.
134 | | */
135 | | function _setBeacon(address newBeacon) private {
136 | | require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
137 | | require(
138 | | Address.isContract(IBeacon(newBeacon).implementation()),
139 | | "ERC1967: beacon implementation is not a contract"
140 | | );
141 | | StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
142 | | }
143 | |
144 | | /**
145 | | * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
146 | | * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
147 | | *
148 | | * Emits a {BeaconUpgraded} event.
149 | | */
150 | | function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
151 | | _setBeacon(newBeacon);
152 | | emit BeaconUpgraded(newBeacon);
153 | | if (data.length > 0 || forceCall) {
154 | | Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
155 | | }
156 | | }
157 | | }
158 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/Proxy.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
8 | | * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
9 | | * be specified by overriding the virtual {_implementation} function.
10 | | *
11 | | * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
12 | | * different contract through the {_delegate} function.
13 | | *
14 | | * The success and return data of the delegated call will be returned back to the caller of the proxy.
15 | | */
16 | | abstract contract Proxy {
17 | | /**
18 | | * @dev Delegates the current call to `implementation`.
19 | | *
20 | | * This function does not return to its internal call site, it will return directly to the external caller.
21 | | */
22 | * | function _delegate(address implementation) internal virtual {
23 | | assembly {
24 | | // Copy msg.data. We take full control of memory in this inline assembly
25 | | // block because it will not return to Solidity code. We overwrite the
26 | | // Solidity scratch pad at memory position 0.
27 | * | calldatacopy(0, 0, calldatasize())
28 | |
29 | | // Call the implementation.
30 | | // out and outsize are 0 because we don't know the size yet.
31 | * | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
32 | |
33 | | // Copy the returned data.
34 | * | returndatacopy(0, 0, returndatasize())
35 | |
36 | * | switch result
37 | | // delegatecall returns 0 on error.
38 | * | case 0 {
39 | * | revert(0, returndatasize())
40 | | }
41 | | default {
42 | * | return(0, returndatasize())
43 | | }
44 | | }
45 | | }
46 | |
47 | | /**
48 | | * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
49 | | * and {_fallback} should delegate.
50 | | */
51 | | function _implementation() internal view virtual returns (address);
52 | |
53 | | /**
54 | | * @dev Delegates the current call to the address returned by `_implementation()`.
55 | | *
56 | | * This function does not return to its internal call site, it will return directly to the external caller.
57 | | */
58 | * | function _fallback() internal virtual {
59 | * | _beforeFallback();
60 | * | _delegate(_implementation());
61 | | }
62 | |
63 | | /**
64 | | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
65 | | * function in the contract matches the call data.
66 | | */
67 | | fallback() external payable virtual {
68 | * | _fallback();
69 | | }
70 | |
71 | | /**
72 | | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
73 | | * is empty.
74 | | */
75 | | receive() external payable virtual {
76 | * | _fallback();
77 | | }
78 | |
79 | | /**
80 | | * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
81 | | * call, or as part of the Solidity `fallback` or `receive` functions.
82 | | *
83 | | * If overridden should call `super._beforeFallback()`.
84 | | */
85 | * | function _beforeFallback() internal virtual {}
86 | | }
87 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev This is the interface that {BeaconProxy} expects of its beacon.
8 | | */
9 | | interface IBeacon {
10 | | /**
11 | | * @dev Must return an address that can be used as a delegate call target.
12 | | *
13 | | * {BeaconProxy} will check that this address is a contract.
14 | | */
15 | | function implementation() external view returns (address);
16 | | }
17 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./TransparentUpgradeableProxy.sol";
7 | | import "../../access/Ownable.sol";
8 | |
9 | | /**
10 | | * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
11 | | * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
12 | | */
13 | * | contract ProxyAdmin is Ownable {
14 | | /**
15 | | * @dev Returns the current implementation of `proxy`.
16 | | *
17 | | * Requirements:
18 | | *
19 | | * - This contract must be the admin of `proxy`.
20 | | */
21 | | function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
22 | | // We need to manually run the static call since the getter cannot be flagged as view
23 | | // bytes4(keccak256("implementation()")) == 0x5c60da1b
24 | | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
25 | | require(success);
26 | | return abi.decode(returndata, (address));
27 | | }
28 | |
29 | | /**
30 | | * @dev Returns the current admin of `proxy`.
31 | | *
32 | | * Requirements:
33 | | *
34 | | * - This contract must be the admin of `proxy`.
35 | | */
36 | | function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {
37 | | // We need to manually run the static call since the getter cannot be flagged as view
38 | | // bytes4(keccak256("admin()")) == 0xf851a440
39 | | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
40 | | require(success);
41 | | return abi.decode(returndata, (address));
42 | | }
43 | |
44 | | /**
45 | | * @dev Changes the admin of `proxy` to `newAdmin`.
46 | | *
47 | | * Requirements:
48 | | *
49 | | * - This contract must be the current admin of `proxy`.
50 | | */
51 | | function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
52 | | proxy.changeAdmin(newAdmin);
53 | | }
54 | |
55 | | /**
56 | | * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
57 | | *
58 | | * Requirements:
59 | | *
60 | | * - This contract must be the admin of `proxy`.
61 | | */
62 | | function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
63 | | proxy.upgradeTo(implementation);
64 | | }
65 | |
66 | | /**
67 | | * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
68 | | * {TransparentUpgradeableProxy-upgradeToAndCall}.
69 | | *
70 | | * Requirements:
71 | | *
72 | | * - This contract must be the admin of `proxy`.
73 | | */
74 | | function upgradeAndCall(
75 | | ITransparentUpgradeableProxy proxy,
76 | | address implementation,
77 | | bytes memory data
78 | | ) public payable virtual onlyOwner {
79 | | proxy.upgradeToAndCall{value: msg.value}(implementation, data);
80 | | }
81 | | }
82 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../ERC1967/ERC1967Proxy.sol";
7 | |
8 | | /**
9 | | * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
10 | | * does not implement this interface directly, and some of its functions are implemented by an internal dispatch
11 | | * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
12 | | * include them in the ABI so this interface must be used to interact with it.
13 | | */
14 | | interface ITransparentUpgradeableProxy is IERC1967 {
15 | | function admin() external view returns (address);
16 | |
17 | | function implementation() external view returns (address);
18 | |
19 | | function changeAdmin(address) external;
20 | |
21 | | function upgradeTo(address) external;
22 | |
23 | | function upgradeToAndCall(address, bytes memory) external payable;
24 | | }
25 | |
26 | | /**
27 | | * @dev This contract implements a proxy that is upgradeable by an admin.
28 | | *
29 | | * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
30 | | * clashing], which can potentially be used in an attack, this contract uses the
31 | | * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
32 | | * things that go hand in hand:
33 | | *
34 | | * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
35 | | * that call matches one of the admin functions exposed by the proxy itself.
36 | | * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
37 | | * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
38 | | * "admin cannot fallback to proxy target".
39 | | *
40 | | * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
41 | | * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
42 | | * to sudden errors when trying to call a function from the proxy implementation.
43 | | *
44 | | * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
45 | | * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
46 | | *
47 | | * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
48 | | * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch
49 | | * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
50 | | * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
51 | | * implementation.
52 | | *
53 | | * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler
54 | | * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function
55 | | * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could
56 | | * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.
57 | | */
58 | * | contract TransparentUpgradeableProxy is ERC1967Proxy {
59 | | /**
60 | | * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
61 | | * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
62 | | */
63 | | constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
64 | | _changeAdmin(admin_);
65 | | }
66 | |
67 | | /**
68 | | * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
69 | | *
70 | | * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the
71 | | * implementation provides a function with the same selector.
72 | | */
73 | | modifier ifAdmin() {
74 | | if (msg.sender == _getAdmin()) {
75 | | _;
76 | | } else {
77 | | _fallback();
78 | | }
79 | | }
80 | |
81 | | /**
82 | | * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior
83 | | */
84 | * | function _fallback() internal virtual override {
85 | * | if (msg.sender == _getAdmin()) {
86 | | bytes memory ret;
87 | | bytes4 selector = msg.sig;
88 | | if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {
89 | | ret = _dispatchUpgradeTo();
90 | | } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
91 | | ret = _dispatchUpgradeToAndCall();
92 | | } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {
93 | | ret = _dispatchChangeAdmin();
94 | | } else if (selector == ITransparentUpgradeableProxy.admin.selector) {
95 | | ret = _dispatchAdmin();
96 | | } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {
97 | | ret = _dispatchImplementation();
98 | | } else {
99 | | revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target");
100 | | }
101 | | assembly {
102 | | return(add(ret, 0x20), mload(ret))
103 | | }
104 | | } else {
105 | * | super._fallback();
106 | | }
107 | | }
108 | |
109 | | /**
110 | | * @dev Returns the current admin.
111 | | *
112 | | * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
113 | | * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
114 | | * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
115 | | */
116 | | function _dispatchAdmin() private returns (bytes memory) {
117 | | _requireZeroValue();
118 | |
119 | | address admin = _getAdmin();
120 | | return abi.encode(admin);
121 | | }
122 | |
123 | | /**
124 | | * @dev Returns the current implementation.
125 | | *
126 | | * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
127 | | * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
128 | | * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
129 | | */
130 | | function _dispatchImplementation() private returns (bytes memory) {
131 | | _requireZeroValue();
132 | |
133 | | address implementation = _implementation();
134 | | return abi.encode(implementation);
135 | | }
136 | |
137 | | /**
138 | | * @dev Changes the admin of the proxy.
139 | | *
140 | | * Emits an {AdminChanged} event.
141 | | */
142 | | function _dispatchChangeAdmin() private returns (bytes memory) {
143 | | _requireZeroValue();
144 | |
145 | | address newAdmin = abi.decode(msg.data[4:], (address));
146 | | _changeAdmin(newAdmin);
147 | |
148 | | return "";
149 | | }
150 | |
151 | | /**
152 | | * @dev Upgrade the implementation of the proxy.
153 | | */
154 | | function _dispatchUpgradeTo() private returns (bytes memory) {
155 | | _requireZeroValue();
156 | |
157 | | address newImplementation = abi.decode(msg.data[4:], (address));
158 | | _upgradeToAndCall(newImplementation, bytes(""), false);
159 | |
160 | | return "";
161 | | }
162 | |
163 | | /**
164 | | * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
165 | | * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
166 | | * proxied contract.
167 | | */
168 | | function _dispatchUpgradeToAndCall() private returns (bytes memory) {
169 | | (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
170 | | _upgradeToAndCall(newImplementation, data, true);
171 | |
172 | | return "";
173 | | }
174 | |
175 | | /**
176 | | * @dev Returns the current admin.
177 | | *
178 | | * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead.
179 | | */
180 | | function _admin() internal view virtual returns (address) {
181 | | return _getAdmin();
182 | | }
183 | |
184 | | /**
185 | | * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to
186 | | * emulate some proxy functions being non-payable while still allowing value to pass through.
187 | | */
188 | | function _requireZeroValue() private {
189 | | require(msg.value == 0);
190 | | }
191 | | }
192 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Contract module that helps prevent reentrant calls to a function.
8 | | *
9 | | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
10 | | * available, which can be applied to functions to make sure there are no nested
11 | | * (reentrant) calls to them.
12 | | *
13 | | * Note that because there is a single `nonReentrant` guard, functions marked as
14 | | * `nonReentrant` may not call one another. This can be worked around by making
15 | | * those functions `private`, and then adding `external` `nonReentrant` entry
16 | | * points to them.
17 | | *
18 | | * TIP: If you would like to learn more about reentrancy and alternative ways
19 | | * to protect against it, check out our blog post
20 | | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
21 | | */
22 | | abstract contract ReentrancyGuard {
23 | | // Booleans are more expensive than uint256 or any type that takes up a full
24 | | // word because each write operation emits an extra SLOAD to first read the
25 | | // slot's contents, replace the bits taken up by the boolean, and then write
26 | | // back. This is the compiler's defense against contract upgrades and
27 | | // pointer aliasing, and it cannot be disabled.
28 | |
29 | | // The values being non-zero value makes deployment a bit more expensive,
30 | | // but in exchange the refund on every call to nonReentrant will be lower in
31 | | // amount. Since refunds are capped to a percentage of the total
32 | | // transaction's gas, it is best to keep them low in cases like this one, to
33 | | // increase the likelihood of the full refund coming into effect.
34 | * | uint256 private constant _NOT_ENTERED = 1;
35 | * | uint256 private constant _ENTERED = 2;
36 | |
37 | | uint256 private _status;
38 | |
39 | | constructor() {
40 | | _status = _NOT_ENTERED;
41 | | }
42 | |
43 | | /**
44 | | * @dev Prevents a contract from calling itself, directly or indirectly.
45 | | * Calling a `nonReentrant` function from another `nonReentrant`
46 | | * function is not supported. It is possible to prevent this from happening
47 | | * by making the `nonReentrant` function external, and making it call a
48 | | * `private` function that does the actual work.
49 | | */
50 | | modifier nonReentrant() {
51 | * | _nonReentrantBefore();
52 | | _;
53 | * | _nonReentrantAfter();
54 | | }
55 | |
56 | * | function _nonReentrantBefore() private {
57 | | // On the first call to nonReentrant, _status will be _NOT_ENTERED
58 | * | require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
59 | |
60 | | // Any calls to nonReentrant after this point will fail
61 | * | _status = _ENTERED;
62 | | }
63 | |
64 | * | function _nonReentrantAfter() private {
65 | | // By storing the original value once again, a refund is triggered (see
66 | | // https://eips.ethereum.org/EIPS/eip-2200)
67 | * | _status = _NOT_ENTERED;
68 | | }
69 | |
70 | | /**
71 | | * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
72 | | * `nonReentrant` function in the call stack.
73 | | */
74 | | function _reentrancyGuardEntered() internal view returns (bool) {
75 | | return _status == _ENTERED;
76 | | }
77 | | }
78 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../../utils/introspection/IERC165.sol";
7 | |
8 | | /**
9 | | * @dev _Available since v3.1._
10 | | */
11 | | interface IERC1155Receiver is IERC165 {
12 | | /**
13 | | * @dev Handles the receipt of a single ERC1155 token type. This function is
14 | | * called at the end of a `safeTransferFrom` after the balance has been updated.
15 | | *
16 | | * NOTE: To accept the transfer, this must return
17 | | * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
18 | | * (i.e. 0xf23a6e61, or its own function selector).
19 | | *
20 | | * @param operator The address which initiated the transfer (i.e. msg.sender)
21 | | * @param from The address which previously owned the token
22 | | * @param id The ID of the token being transferred
23 | | * @param value The amount of tokens being transferred
24 | | * @param data Additional data with no specified format
25 | | * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
26 | | */
27 | | function onERC1155Received(
28 | | address operator,
29 | | address from,
30 | | uint256 id,
31 | | uint256 value,
32 | | bytes calldata data
33 | | ) external returns (bytes4);
34 | |
35 | | /**
36 | | * @dev Handles the receipt of a multiple ERC1155 token types. This function
37 | | * is called at the end of a `safeBatchTransferFrom` after the balances have
38 | | * been updated.
39 | | *
40 | | * NOTE: To accept the transfer(s), this must return
41 | | * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
42 | | * (i.e. 0xbc197c81, or its own function selector).
43 | | *
44 | | * @param operator The address which initiated the batch transfer (i.e. msg.sender)
45 | | * @param from The address which previously owned the token
46 | | * @param ids An array containing ids of each token being transferred (order and length must match values array)
47 | | * @param values An array containing amounts of each token being transferred (order and length must match ids array)
48 | | * @param data Additional data with no specified format
49 | | * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
50 | | */
51 | | function onERC1155BatchReceived(
52 | | address operator,
53 | | address from,
54 | | uint256[] calldata ids,
55 | | uint256[] calldata values,
56 | | bytes calldata data
57 | | ) external returns (bytes4);
58 | | }
59 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./IERC20.sol";
7 | | import "./extensions/IERC20Metadata.sol";
8 | | import "../../utils/Context.sol";
9 | |
10 | | /**
11 | | * @dev Implementation of the {IERC20} interface.
12 | | *
13 | | * This implementation is agnostic to the way tokens are created. This means
14 | | * that a supply mechanism has to be added in a derived contract using {_mint}.
15 | | * For a generic mechanism see {ERC20PresetMinterPauser}.
16 | | *
17 | | * TIP: For a detailed writeup see our guide
18 | | * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
19 | | * to implement supply mechanisms].
20 | | *
21 | | * The default value of {decimals} is 18. To change this, you should override
22 | | * this function so it returns a different value.
23 | | *
24 | | * We have followed general OpenZeppelin Contracts guidelines: functions revert
25 | | * instead returning `false` on failure. This behavior is nonetheless
26 | | * conventional and does not conflict with the expectations of ERC20
27 | | * applications.
28 | | *
29 | | * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
30 | | * This allows applications to reconstruct the allowance for all accounts just
31 | | * by listening to said events. Other implementations of the EIP may not emit
32 | | * these events, as it isn't required by the specification.
33 | | *
34 | | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
35 | | * functions have been added to mitigate the well-known issues around setting
36 | | * allowances. See {IERC20-approve}.
37 | | */
38 | | contract ERC20 is Context, IERC20, IERC20Metadata {
39 | | mapping(address => uint256) private _balances;
40 | |
41 | | mapping(address => mapping(address => uint256)) private _allowances;
42 | |
43 | | uint256 private _totalSupply;
44 | |
45 | | string private _name;
46 | | string private _symbol;
47 | |
48 | | /**
49 | | * @dev Sets the values for {name} and {symbol}.
50 | | *
51 | | * All two of these values are immutable: they can only be set once during
52 | | * construction.
53 | | */
54 | | constructor(string memory name_, string memory symbol_) {
55 | | _name = name_;
56 | | _symbol = symbol_;
57 | | }
58 | |
59 | | /**
60 | | * @dev Returns the name of the token.
61 | | */
62 | | function name() public view virtual override returns (string memory) {
63 | | return _name;
64 | | }
65 | |
66 | | /**
67 | | * @dev Returns the symbol of the token, usually a shorter version of the
68 | | * name.
69 | | */
70 | | function symbol() public view virtual override returns (string memory) {
71 | | return _symbol;
72 | | }
73 | |
74 | | /**
75 | | * @dev Returns the number of decimals used to get its user representation.
76 | | * For example, if `decimals` equals `2`, a balance of `505` tokens should
77 | | * be displayed to a user as `5.05` (`505 / 10 ** 2`).
78 | | *
79 | | * Tokens usually opt for a value of 18, imitating the relationship between
80 | | * Ether and Wei. This is the default value returned by this function, unless
81 | | * it's overridden.
82 | | *
83 | | * NOTE: This information is only used for _display_ purposes: it in
84 | | * no way affects any of the arithmetic of the contract, including
85 | | * {IERC20-balanceOf} and {IERC20-transfer}.
86 | | */
87 | | function decimals() public view virtual override returns (uint8) {
88 | | return 18;
89 | | }
90 | |
91 | | /**
92 | | * @dev See {IERC20-totalSupply}.
93 | | */
94 | * | function totalSupply() public view virtual override returns (uint256) {
95 | * | return _totalSupply;
96 | | }
97 | |
98 | | /**
99 | | * @dev See {IERC20-balanceOf}.
100 | | */
101 | * | function balanceOf(address account) public view virtual override returns (uint256) {
102 | * | return _balances[account];
103 | | }
104 | |
105 | | /**
106 | | * @dev See {IERC20-transfer}.
107 | | *
108 | | * Requirements:
109 | | *
110 | | * - `to` cannot be the zero address.
111 | | * - the caller must have a balance of at least `amount`.
112 | | */
113 | * | function transfer(address to, uint256 amount) public virtual override returns (bool) {
114 | * | address owner = _msgSender();
115 | * | _transfer(owner, to, amount);
116 | * | return true;
117 | | }
118 | |
119 | | /**
120 | | * @dev See {IERC20-allowance}.
121 | | */
122 | * | function allowance(address owner, address spender) public view virtual override returns (uint256) {
123 | * | return _allowances[owner][spender];
124 | | }
125 | |
126 | | /**
127 | | * @dev See {IERC20-approve}.
128 | | *
129 | | * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
130 | | * `transferFrom`. This is semantically equivalent to an infinite approval.
131 | | *
132 | | * Requirements:
133 | | *
134 | | * - `spender` cannot be the zero address.
135 | | */
136 | * | function approve(address spender, uint256 amount) public virtual override returns (bool) {
137 | * | address owner = _msgSender();
138 | * | _approve(owner, spender, amount);
139 | * | return true;
140 | | }
141 | |
142 | | /**
143 | | * @dev See {IERC20-transferFrom}.
144 | | *
145 | | * Emits an {Approval} event indicating the updated allowance. This is not
146 | | * required by the EIP. See the note at the beginning of {ERC20}.
147 | | *
148 | | * NOTE: Does not update the allowance if the current allowance
149 | | * is the maximum `uint256`.
150 | | *
151 | | * Requirements:
152 | | *
153 | | * - `from` and `to` cannot be the zero address.
154 | | * - `from` must have a balance of at least `amount`.
155 | | * - the caller must have allowance for ``from``'s tokens of at least
156 | | * `amount`.
157 | | */
158 | * | function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
159 | * | address spender = _msgSender();
160 | * | _spendAllowance(from, spender, amount);
161 | * | _transfer(from, to, amount);
162 | * | return true;
163 | | }
164 | |
165 | | /**
166 | | * @dev Atomically increases the allowance granted to `spender` by the caller.
167 | | *
168 | | * This is an alternative to {approve} that can be used as a mitigation for
169 | | * problems described in {IERC20-approve}.
170 | | *
171 | | * Emits an {Approval} event indicating the updated allowance.
172 | | *
173 | | * Requirements:
174 | | *
175 | | * - `spender` cannot be the zero address.
176 | | */
177 | | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
178 | | address owner = _msgSender();
179 | | _approve(owner, spender, allowance(owner, spender) + addedValue);
180 | | return true;
181 | | }
182 | |
183 | | /**
184 | | * @dev Atomically decreases the allowance granted to `spender` by the caller.
185 | | *
186 | | * This is an alternative to {approve} that can be used as a mitigation for
187 | | * problems described in {IERC20-approve}.
188 | | *
189 | | * Emits an {Approval} event indicating the updated allowance.
190 | | *
191 | | * Requirements:
192 | | *
193 | | * - `spender` cannot be the zero address.
194 | | * - `spender` must have allowance for the caller of at least
195 | | * `subtractedValue`.
196 | | */
197 | | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
198 | | address owner = _msgSender();
199 | | uint256 currentAllowance = allowance(owner, spender);
200 | | require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
201 | | unchecked {
202 | | _approve(owner, spender, currentAllowance - subtractedValue);
203 | | }
204 | |
205 | | return true;
206 | | }
207 | |
208 | | /**
209 | | * @dev Moves `amount` of tokens from `from` to `to`.
210 | | *
211 | | * This internal function is equivalent to {transfer}, and can be used to
212 | | * e.g. implement automatic token fees, slashing mechanisms, etc.
213 | | *
214 | | * Emits a {Transfer} event.
215 | | *
216 | | * Requirements:
217 | | *
218 | | * - `from` cannot be the zero address.
219 | | * - `to` cannot be the zero address.
220 | | * - `from` must have a balance of at least `amount`.
221 | | */
222 | * | function _transfer(address from, address to, uint256 amount) internal virtual {
223 | * | require(from != address(0), "ERC20: transfer from the zero address");
224 | * | require(to != address(0), "ERC20: transfer to the zero address");
225 | |
226 | * | _beforeTokenTransfer(from, to, amount);
227 | |
228 | * | uint256 fromBalance = _balances[from];
229 | * | require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
230 | | unchecked {
231 | * | _balances[from] = fromBalance - amount;
232 | | // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
233 | | // decrementing then incrementing.
234 | * | _balances[to] += amount;
235 | | }
236 | |
237 | * | emit Transfer(from, to, amount);
238 | |
239 | * | _afterTokenTransfer(from, to, amount);
240 | | }
241 | |
242 | | /** @dev Creates `amount` tokens and assigns them to `account`, increasing
243 | | * the total supply.
244 | | *
245 | | * Emits a {Transfer} event with `from` set to the zero address.
246 | | *
247 | | * Requirements:
248 | | *
249 | | * - `account` cannot be the zero address.
250 | | */
251 | * | function _mint(address account, uint256 amount) internal virtual {
252 | * | require(account != address(0), "ERC20: mint to the zero address");
253 | |
254 | * | _beforeTokenTransfer(address(0), account, amount);
255 | |
256 | * | _totalSupply += amount;
257 | | unchecked {
258 | | // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
259 | * | _balances[account] += amount;
260 | | }
261 | * | emit Transfer(address(0), account, amount);
262 | |
263 | * | _afterTokenTransfer(address(0), account, amount);
264 | | }
265 | |
266 | | /**
267 | | * @dev Destroys `amount` tokens from `account`, reducing the
268 | | * total supply.
269 | | *
270 | | * Emits a {Transfer} event with `to` set to the zero address.
271 | | *
272 | | * Requirements:
273 | | *
274 | | * - `account` cannot be the zero address.
275 | | * - `account` must have at least `amount` tokens.
276 | | */
277 | * | function _burn(address account, uint256 amount) internal virtual {
278 | * | require(account != address(0), "ERC20: burn from the zero address");
279 | |
280 | * | _beforeTokenTransfer(account, address(0), amount);
281 | |
282 | * | uint256 accountBalance = _balances[account];
283 | * | require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
284 | | unchecked {
285 | * | _balances[account] = accountBalance - amount;
286 | | // Overflow not possible: amount <= accountBalance <= totalSupply.
287 | * | _totalSupply -= amount;
288 | | }
289 | |
290 | * | emit Transfer(account, address(0), amount);
291 | |
292 | * | _afterTokenTransfer(account, address(0), amount);
293 | | }
294 | |
295 | | /**
296 | | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
297 | | *
298 | | * This internal function is equivalent to `approve`, and can be used to
299 | | * e.g. set automatic allowances for certain subsystems, etc.
300 | | *
301 | | * Emits an {Approval} event.
302 | | *
303 | | * Requirements:
304 | | *
305 | | * - `owner` cannot be the zero address.
306 | | * - `spender` cannot be the zero address.
307 | | */
308 | * | function _approve(address owner, address spender, uint256 amount) internal virtual {
309 | * | require(owner != address(0), "ERC20: approve from the zero address");
310 | * | require(spender != address(0), "ERC20: approve to the zero address");
311 | |
312 | * | _allowances[owner][spender] = amount;
313 | * | emit Approval(owner, spender, amount);
314 | | }
315 | |
316 | | /**
317 | | * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
318 | | *
319 | | * Does not update the allowance amount in case of infinite allowance.
320 | | * Revert if not enough allowance is available.
321 | | *
322 | | * Might emit an {Approval} event.
323 | | */
324 | * | function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
325 | * | uint256 currentAllowance = allowance(owner, spender);
326 | * | if (currentAllowance != type(uint256).max) {
327 | * | require(currentAllowance >= amount, "ERC20: insufficient allowance");
328 | | unchecked {
329 | * | _approve(owner, spender, currentAllowance - amount);
330 | | }
331 | | }
332 | | }
333 | |
334 | | /**
335 | | * @dev Hook that is called before any transfer of tokens. This includes
336 | | * minting and burning.
337 | | *
338 | | * Calling conditions:
339 | | *
340 | | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
341 | | * will be transferred to `to`.
342 | | * - when `from` is zero, `amount` tokens will be minted for `to`.
343 | | * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
344 | | * - `from` and `to` are never both zero.
345 | | *
346 | | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
347 | | */
348 | * | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
349 | |
350 | | /**
351 | | * @dev Hook that is called after any transfer of tokens. This includes
352 | | * minting and burning.
353 | | *
354 | | * Calling conditions:
355 | | *
356 | | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
357 | | * has been transferred to `to`.
358 | | * - when `from` is zero, `amount` tokens have been minted for `to`.
359 | | * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
360 | | * - `from` and `to` are never both zero.
361 | | *
362 | | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
363 | | */
364 | * | function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
365 | | }
366 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Interface of the ERC20 standard as defined in the EIP.
8 | | */
9 | | interface IERC20 {
10 | | /**
11 | | * @dev Emitted when `value` tokens are moved from one account (`from`) to
12 | | * another (`to`).
13 | | *
14 | | * Note that `value` may be zero.
15 | | */
16 | | event Transfer(address indexed from, address indexed to, uint256 value);
17 | |
18 | | /**
19 | | * @dev Emitted when the allowance of a `spender` for an `owner` is set by
20 | | * a call to {approve}. `value` is the new allowance.
21 | | */
22 | | event Approval(address indexed owner, address indexed spender, uint256 value);
23 | |
24 | | /**
25 | | * @dev Returns the amount of tokens in existence.
26 | | */
27 | | function totalSupply() external view returns (uint256);
28 | |
29 | | /**
30 | | * @dev Returns the amount of tokens owned by `account`.
31 | | */
32 | | function balanceOf(address account) external view returns (uint256);
33 | |
34 | | /**
35 | | * @dev Moves `amount` tokens from the caller's account to `to`.
36 | | *
37 | | * Returns a boolean value indicating whether the operation succeeded.
38 | | *
39 | | * Emits a {Transfer} event.
40 | | */
41 | | function transfer(address to, uint256 amount) external returns (bool);
42 | |
43 | | /**
44 | | * @dev Returns the remaining number of tokens that `spender` will be
45 | | * allowed to spend on behalf of `owner` through {transferFrom}. This is
46 | | * zero by default.
47 | | *
48 | | * This value changes when {approve} or {transferFrom} are called.
49 | | */
50 | | function allowance(address owner, address spender) external view returns (uint256);
51 | |
52 | | /**
53 | | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
54 | | *
55 | | * Returns a boolean value indicating whether the operation succeeded.
56 | | *
57 | | * IMPORTANT: Beware that changing an allowance with this method brings the risk
58 | | * that someone may use both the old and the new allowance by unfortunate
59 | | * transaction ordering. One possible solution to mitigate this race
60 | | * condition is to first reduce the spender's allowance to 0 and set the
61 | | * desired value afterwards:
62 | | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
63 | | *
64 | | * Emits an {Approval} event.
65 | | */
66 | | function approve(address spender, uint256 amount) external returns (bool);
67 | |
68 | | /**
69 | | * @dev Moves `amount` tokens from `from` to `to` using the
70 | | * allowance mechanism. `amount` is then deducted from the caller's
71 | | * allowance.
72 | | *
73 | | * Returns a boolean value indicating whether the operation succeeded.
74 | | *
75 | | * Emits a {Transfer} event.
76 | | */
77 | | function transferFrom(address from, address to, uint256 amount) external returns (bool);
78 | | }
79 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./IERC20Permit.sol";
7 | | import "../ERC20.sol";
8 | | import "../../../utils/cryptography/ECDSA.sol";
9 | | import "../../../utils/cryptography/EIP712.sol";
10 | | import "../../../utils/Counters.sol";
11 | |
12 | | /**
13 | | * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
14 | | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
15 | | *
16 | | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
17 | | * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
18 | | * need to send a transaction, and thus is not required to hold Ether at all.
19 | | *
20 | | * _Available since v3.4._
21 | | */
22 | | abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
23 | | using Counters for Counters.Counter;
24 | |
25 | | mapping(address => Counters.Counter) private _nonces;
26 | |
27 | | // solhint-disable-next-line var-name-mixedcase
28 | | bytes32 private constant _PERMIT_TYPEHASH =
29 | | keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
30 | | /**
31 | | * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
32 | | * However, to ensure consistency with the upgradeable transpiler, we will continue
33 | | * to reserve a slot.
34 | | * @custom:oz-renamed-from _PERMIT_TYPEHASH
35 | | */
36 | | // solhint-disable-next-line var-name-mixedcase
37 | | bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
38 | |
39 | | /**
40 | | * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
41 | | *
42 | | * It's a good idea to use the same `name` that is defined as the ERC20 token name.
43 | | */
44 | | constructor(string memory name) EIP712(name, "1") {}
45 | |
46 | | /**
47 | | * @dev See {IERC20Permit-permit}.
48 | | */
49 | | function permit(
50 | | address owner,
51 | | address spender,
52 | | uint256 value,
53 | | uint256 deadline,
54 | | uint8 v,
55 | | bytes32 r,
56 | | bytes32 s
57 | | ) public virtual override {
58 | | require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
59 | |
60 | | bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
61 | |
62 | | bytes32 hash = _hashTypedDataV4(structHash);
63 | |
64 | | address signer = ECDSA.recover(hash, v, r, s);
65 | | require(signer == owner, "ERC20Permit: invalid signature");
66 | |
67 | | _approve(owner, spender, value);
68 | | }
69 | |
70 | | /**
71 | | * @dev See {IERC20Permit-nonces}.
72 | | */
73 | | function nonces(address owner) public view virtual override returns (uint256) {
74 | | return _nonces[owner].current();
75 | | }
76 | |
77 | | /**
78 | | * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
79 | | */
80 | | // solhint-disable-next-line func-name-mixedcase
81 | | function DOMAIN_SEPARATOR() external view override returns (bytes32) {
82 | | return _domainSeparatorV4();
83 | | }
84 | |
85 | | /**
86 | | * @dev "Consume a nonce": return the current value and increment.
87 | | *
88 | | * _Available since v4.1._
89 | | */
90 | | function _useNonce(address owner) internal virtual returns (uint256 current) {
91 | | Counters.Counter storage nonce = _nonces[owner];
92 | | current = nonce.current();
93 | | nonce.increment();
94 | | }
95 | | }
96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./ERC20Permit.sol";
7 | | import "../../../interfaces/IERC5805.sol";
8 | | import "../../../utils/math/Math.sol";
9 | | import "../../../utils/math/SafeCast.sol";
10 | | import "../../../utils/cryptography/ECDSA.sol";
11 | |
12 | | /**
13 | | * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,
14 | | * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.
15 | | *
16 | | * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.
17 | | *
18 | | * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either
19 | | * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting
20 | | * power can be queried through the public accessors {getVotes} and {getPastVotes}.
21 | | *
22 | | * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it
23 | | * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
24 | | *
25 | | * _Available since v4.2._
26 | | */
27 | | abstract contract ERC20Votes is ERC20Permit, IERC5805 {
28 | | struct Checkpoint {
29 | | uint32 fromBlock;
30 | | uint224 votes;
31 | | }
32 | |
33 | | bytes32 private constant _DELEGATION_TYPEHASH =
34 | | keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
35 | |
36 | | mapping(address => address) private _delegates;
37 | | mapping(address => Checkpoint[]) private _checkpoints;
38 | | Checkpoint[] private _totalSupplyCheckpoints;
39 | |
40 | | /**
41 | | * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
42 | | */
43 | | function clock() public view virtual override returns (uint48) {
44 | | return SafeCast.toUint48(block.number);
45 | | }
46 | |
47 | | /**
48 | | * @dev Description of the clock
49 | | */
50 | | // solhint-disable-next-line func-name-mixedcase
51 | | function CLOCK_MODE() public view virtual override returns (string memory) {
52 | | // Check that the clock was not modified
53 | | require(clock() == block.number, "ERC20Votes: broken clock mode");
54 | | return "mode=blocknumber&from=default";
55 | | }
56 | |
57 | | /**
58 | | * @dev Get the `pos`-th checkpoint for `account`.
59 | | */
60 | | function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {
61 | | return _checkpoints[account][pos];
62 | | }
63 | |
64 | | /**
65 | | * @dev Get number of checkpoints for `account`.
66 | | */
67 | | function numCheckpoints(address account) public view virtual returns (uint32) {
68 | | return SafeCast.toUint32(_checkpoints[account].length);
69 | | }
70 | |
71 | | /**
72 | | * @dev Get the address `account` is currently delegating to.
73 | | */
74 | | function delegates(address account) public view virtual override returns (address) {
75 | | return _delegates[account];
76 | | }
77 | |
78 | | /**
79 | | * @dev Gets the current votes balance for `account`
80 | | */
81 | | function getVotes(address account) public view virtual override returns (uint256) {
82 | | uint256 pos = _checkpoints[account].length;
83 | | unchecked {
84 | | return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
85 | | }
86 | | }
87 | |
88 | | /**
89 | | * @dev Retrieve the number of votes for `account` at the end of `timepoint`.
90 | | *
91 | | * Requirements:
92 | | *
93 | | * - `timepoint` must be in the past
94 | | */
95 | | function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) {
96 | | require(timepoint < clock(), "ERC20Votes: future lookup");
97 | | return _checkpointsLookup(_checkpoints[account], timepoint);
98 | | }
99 | |
100 | | /**
101 | | * @dev Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances.
102 | | * It is NOT the sum of all the delegated votes!
103 | | *
104 | | * Requirements:
105 | | *
106 | | * - `timepoint` must be in the past
107 | | */
108 | | function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) {
109 | | require(timepoint < clock(), "ERC20Votes: future lookup");
110 | | return _checkpointsLookup(_totalSupplyCheckpoints, timepoint);
111 | | }
112 | |
113 | | /**
114 | | * @dev Lookup a value in a list of (sorted) checkpoints.
115 | | */
116 | | function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 timepoint) private view returns (uint256) {
117 | | // We run a binary search to look for the last (most recent) checkpoint taken before (or at) `timepoint`.
118 | | //
119 | | // Initially we check if the block is recent to narrow the search range.
120 | | // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
121 | | // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
122 | | // - If the middle checkpoint is after `timepoint`, we look in [low, mid)
123 | | // - If the middle checkpoint is before or equal to `timepoint`, we look in [mid+1, high)
124 | | // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not
125 | | // out of bounds (in which case we're looking too far in the past and the result is 0).
126 | | // Note that if the latest checkpoint available is exactly for `timepoint`, we end up with an index that is
127 | | // past the end of the array, so we technically don't find a checkpoint after `timepoint`, but it works out
128 | | // the same.
129 | | uint256 length = ckpts.length;
130 | |
131 | | uint256 low = 0;
132 | | uint256 high = length;
133 | |
134 | | if (length > 5) {
135 | | uint256 mid = length - Math.sqrt(length);
136 | | if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {
137 | | high = mid;
138 | | } else {
139 | | low = mid + 1;
140 | | }
141 | | }
142 | |
143 | | while (low < high) {
144 | | uint256 mid = Math.average(low, high);
145 | | if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) {
146 | | high = mid;
147 | | } else {
148 | | low = mid + 1;
149 | | }
150 | | }
151 | |
152 | | unchecked {
153 | | return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;
154 | | }
155 | | }
156 | |
157 | | /**
158 | | * @dev Delegate votes from the sender to `delegatee`.
159 | | */
160 | | function delegate(address delegatee) public virtual override {
161 | | _delegate(_msgSender(), delegatee);
162 | | }
163 | |
164 | | /**
165 | | * @dev Delegates votes from signer to `delegatee`
166 | | */
167 | | function delegateBySig(
168 | | address delegatee,
169 | | uint256 nonce,
170 | | uint256 expiry,
171 | | uint8 v,
172 | | bytes32 r,
173 | | bytes32 s
174 | | ) public virtual override {
175 | | require(block.timestamp <= expiry, "ERC20Votes: signature expired");
176 | | address signer = ECDSA.recover(
177 | | _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
178 | | v,
179 | | r,
180 | | s
181 | | );
182 | | require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce");
183 | | _delegate(signer, delegatee);
184 | | }
185 | |
186 | | /**
187 | | * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).
188 | | */
189 | | function _maxSupply() internal view virtual returns (uint224) {
190 | | return type(uint224).max;
191 | | }
192 | |
193 | | /**
194 | | * @dev Snapshots the totalSupply after it has been increased.
195 | | */
196 | | function _mint(address account, uint256 amount) internal virtual override {
197 | | super._mint(account, amount);
198 | | require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes");
199 | |
200 | | _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);
201 | | }
202 | |
203 | | /**
204 | | * @dev Snapshots the totalSupply after it has been decreased.
205 | | */
206 | | function _burn(address account, uint256 amount) internal virtual override {
207 | | super._burn(account, amount);
208 | |
209 | | _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);
210 | | }
211 | |
212 | | /**
213 | | * @dev Move voting power when tokens are transferred.
214 | | *
215 | | * Emits a {IVotes-DelegateVotesChanged} event.
216 | | */
217 | | function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual override {
218 | | super._afterTokenTransfer(from, to, amount);
219 | |
220 | | _moveVotingPower(delegates(from), delegates(to), amount);
221 | | }
222 | |
223 | | /**
224 | | * @dev Change delegation for `delegator` to `delegatee`.
225 | | *
226 | | * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
227 | | */
228 | | function _delegate(address delegator, address delegatee) internal virtual {
229 | | address currentDelegate = delegates(delegator);
230 | | uint256 delegatorBalance = balanceOf(delegator);
231 | | _delegates[delegator] = delegatee;
232 | |
233 | | emit DelegateChanged(delegator, currentDelegate, delegatee);
234 | |
235 | | _moveVotingPower(currentDelegate, delegatee, delegatorBalance);
236 | | }
237 | |
238 | | function _moveVotingPower(address src, address dst, uint256 amount) private {
239 | | if (src != dst && amount > 0) {
240 | | if (src != address(0)) {
241 | | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);
242 | | emit DelegateVotesChanged(src, oldWeight, newWeight);
243 | | }
244 | |
245 | | if (dst != address(0)) {
246 | | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);
247 | | emit DelegateVotesChanged(dst, oldWeight, newWeight);
248 | | }
249 | | }
250 | | }
251 | |
252 | | function _writeCheckpoint(
253 | | Checkpoint[] storage ckpts,
254 | | function(uint256, uint256) view returns (uint256) op,
255 | | uint256 delta
256 | | ) private returns (uint256 oldWeight, uint256 newWeight) {
257 | | uint256 pos = ckpts.length;
258 | |
259 | | unchecked {
260 | | Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);
261 | |
262 | | oldWeight = oldCkpt.votes;
263 | | newWeight = op(oldWeight, delta);
264 | |
265 | | if (pos > 0 && oldCkpt.fromBlock == clock()) {
266 | | _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);
267 | | } else {
268 | | ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(clock()), votes: SafeCast.toUint224(newWeight)}));
269 | | }
270 | | }
271 | | }
272 | |
273 | | function _add(uint256 a, uint256 b) private pure returns (uint256) {
274 | | return a + b;
275 | | }
276 | |
277 | | function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
278 | | return a - b;
279 | | }
280 | |
281 | | /**
282 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
283 | | */
284 | | function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {
285 | | assembly {
286 | | mstore(0, ckpts.slot)
287 | | result.slot := add(keccak256(0, 0x20), pos)
288 | | }
289 | | }
290 | | }
291 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../IERC20.sol";
7 | |
8 | | /**
9 | | * @dev Interface for the optional metadata functions from the ERC20 standard.
10 | | *
11 | | * _Available since v4.1._
12 | | */
13 | | interface IERC20Metadata is IERC20 {
14 | | /**
15 | | * @dev Returns the name of the token.
16 | | */
17 | | function name() external view returns (string memory);
18 | |
19 | | /**
20 | | * @dev Returns the symbol of the token.
21 | | */
22 | | function symbol() external view returns (string memory);
23 | |
24 | | /**
25 | | * @dev Returns the decimals places of the token.
26 | | */
27 | | function decimals() external view returns (uint8);
28 | | }
29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
8 | | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
9 | | *
10 | | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
11 | | * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
12 | | * need to send a transaction, and thus is not required to hold Ether at all.
13 | | */
14 | | interface IERC20Permit {
15 | | /**
16 | | * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
17 | | * given ``owner``'s signed approval.
18 | | *
19 | | * IMPORTANT: The same issues {IERC20-approve} has related to transaction
20 | | * ordering also apply here.
21 | | *
22 | | * Emits an {Approval} event.
23 | | *
24 | | * Requirements:
25 | | *
26 | | * - `spender` cannot be the zero address.
27 | | * - `deadline` must be a timestamp in the future.
28 | | * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
29 | | * over the EIP712-formatted function arguments.
30 | | * - the signature must use ``owner``'s current nonce (see {nonces}).
31 | | *
32 | | * For more information on the signature format, see the
33 | | * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
34 | | * section].
35 | | */
36 | | function permit(
37 | | address owner,
38 | | address spender,
39 | | uint256 value,
40 | | uint256 deadline,
41 | | uint8 v,
42 | | bytes32 r,
43 | | bytes32 s
44 | | ) external;
45 | |
46 | | /**
47 | | * @dev Returns the current nonce for `owner`. This value must be
48 | | * included whenever a signature is generated for {permit}.
49 | | *
50 | | * Every successful call to {permit} increases ``owner``'s nonce by one. This
51 | | * prevents a signature from being used multiple times.
52 | | */
53 | | function nonces(address owner) external view returns (uint256);
54 | |
55 | | /**
56 | | * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
57 | | */
58 | | // solhint-disable-next-line func-name-mixedcase
59 | | function DOMAIN_SEPARATOR() external view returns (bytes32);
60 | | }
61 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../IERC20.sol";
7 | | import "../extensions/IERC20Permit.sol";
8 | | import "../../../utils/Address.sol";
9 | |
10 | | /**
11 | | * @title SafeERC20
12 | | * @dev Wrappers around ERC20 operations that throw on failure (when the token
13 | | * contract returns false). Tokens that return no value (and instead revert or
14 | | * throw on failure) are also supported, non-reverting calls are assumed to be
15 | | * successful.
16 | | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
17 | | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
18 | | */
19 | * | library SafeERC20 {
20 | | using Address for address;
21 | |
22 | | /**
23 | | * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
24 | | * non-reverting calls are assumed to be successful.
25 | | */
26 | * | function safeTransfer(IERC20 token, address to, uint256 value) internal {
27 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
28 | | }
29 | |
30 | | /**
31 | | * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
32 | | * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
33 | | */
34 | * | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
35 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
36 | | }
37 | |
38 | | /**
39 | | * @dev Deprecated. This function has issues similar to the ones found in
40 | | * {IERC20-approve}, and its usage is discouraged.
41 | | *
42 | | * Whenever possible, use {safeIncreaseAllowance} and
43 | | * {safeDecreaseAllowance} instead.
44 | | */
45 | * | function safeApprove(IERC20 token, address spender, uint256 value) internal {
46 | | // safeApprove should only be called when setting an initial allowance,
47 | | // or when resetting it to zero. To increase and decrease it, use
48 | | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
49 | * | require(
50 | * | (value == 0) || (token.allowance(address(this), spender) == 0),
51 | | "SafeERC20: approve from non-zero to non-zero allowance"
52 | | );
53 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
54 | | }
55 | |
56 | | /**
57 | | * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
58 | | * non-reverting calls are assumed to be successful.
59 | | */
60 | | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
61 | | uint256 oldAllowance = token.allowance(address(this), spender);
62 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
63 | | }
64 | |
65 | | /**
66 | | * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
67 | | * non-reverting calls are assumed to be successful.
68 | | */
69 | | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
70 | | unchecked {
71 | | uint256 oldAllowance = token.allowance(address(this), spender);
72 | | require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
73 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
74 | | }
75 | | }
76 | |
77 | | /**
78 | | * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
79 | | * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
80 | | * to be set to zero before setting it to a non-zero value, such as USDT.
81 | | */
82 | | function forceApprove(IERC20 token, address spender, uint256 value) internal {
83 | | bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
84 | |
85 | | if (!_callOptionalReturnBool(token, approvalCall)) {
86 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
87 | | _callOptionalReturn(token, approvalCall);
88 | | }
89 | | }
90 | |
91 | | /**
92 | | * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
93 | | * Revert on invalid signature.
94 | | */
95 | | function safePermit(
96 | | IERC20Permit token,
97 | | address owner,
98 | | address spender,
99 | | uint256 value,
100 | | uint256 deadline,
101 | | uint8 v,
102 | | bytes32 r,
103 | | bytes32 s
104 | | ) internal {
105 | | uint256 nonceBefore = token.nonces(owner);
106 | | token.permit(owner, spender, value, deadline, v, r, s);
107 | | uint256 nonceAfter = token.nonces(owner);
108 | | require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
109 | | }
110 | |
111 | | /**
112 | | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
113 | | * on the return value: the return value is optional (but if data is returned, it must not be false).
114 | | * @param token The token targeted by the call.
115 | | * @param data The call data (encoded using abi.encode or one of its variants).
116 | | */
117 | * | function _callOptionalReturn(IERC20 token, bytes memory data) private {
118 | | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
119 | | // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
120 | | // the target address contains contract code and also asserts for success in the low-level call.
121 | |
122 | * | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
123 | * | require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
124 | | }
125 | |
126 | | /**
127 | | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
128 | | * on the return value: the return value is optional (but if data is returned, it must not be false).
129 | | * @param token The token targeted by the call.
130 | | * @param data The call data (encoded using abi.encode or one of its variants).
131 | | *
132 | | * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
133 | | */
134 | | function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
135 | | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
136 | | // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
137 | | // and not revert is the subcall reverts.
138 | |
139 | | (bool success, bytes memory returndata) = address(token).call(data);
140 | | return
141 | | success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
142 | | }
143 | | }
144 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @title ERC721 token receiver interface
8 | | * @dev Interface for any contract that wants to support safeTransfers
9 | | * from ERC721 asset contracts.
10 | | */
11 | | interface IERC721Receiver {
12 | | /**
13 | | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
14 | | * by `operator` from `from`, this function is called.
15 | | *
16 | | * It must return its Solidity selector to confirm the token transfer.
17 | | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
18 | | *
19 | | * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
20 | | */
21 | | function onERC721Received(
22 | | address operator,
23 | | address from,
24 | | uint256 tokenId,
25 | | bytes calldata data
26 | | ) external returns (bytes4);
27 | | }
28 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Address.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
3 | |
4 | | pragma solidity ^0.8.1;
5 | |
6 | | /**
7 | | * @dev Collection of functions related to the address type
8 | | */
9 | * | library Address {
10 | | /**
11 | | * @dev Returns true if `account` is a contract.
12 | | *
13 | | * [IMPORTANT]
14 | | * ====
15 | | * It is unsafe to assume that an address for which this function returns
16 | | * false is an externally-owned account (EOA) and not a contract.
17 | | *
18 | | * Among others, `isContract` will return false for the following
19 | | * types of addresses:
20 | | *
21 | | * - an externally-owned account
22 | | * - a contract in construction
23 | | * - an address where a contract will be created
24 | | * - an address where a contract lived, but was destroyed
25 | | *
26 | | * Furthermore, `isContract` will also return true if the target contract within
27 | | * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
28 | | * which only has an effect at the end of a transaction.
29 | | * ====
30 | | *
31 | | * [IMPORTANT]
32 | | * ====
33 | | * You shouldn't rely on `isContract` to protect against flash loan attacks!
34 | | *
35 | | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
36 | | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
37 | | * constructor.
38 | | * ====
39 | | */
40 | * | function isContract(address account) internal view returns (bool) {
41 | | // This method relies on extcodesize/address.code.length, which returns 0
42 | | // for contracts in construction, since the code is only stored at the end
43 | | // of the constructor execution.
44 | |
45 | * | return account.code.length > 0;
46 | | }
47 | |
48 | | /**
49 | | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
50 | | * `recipient`, forwarding all available gas and reverting on errors.
51 | | *
52 | | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
53 | | * of certain opcodes, possibly making contracts go over the 2300 gas limit
54 | | * imposed by `transfer`, making them unable to receive funds via
55 | | * `transfer`. {sendValue} removes this limitation.
56 | | *
57 | | * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
58 | | *
59 | | * IMPORTANT: because control is transferred to `recipient`, care must be
60 | | * taken to not create reentrancy vulnerabilities. Consider using
61 | | * {ReentrancyGuard} or the
62 | | * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
63 | | */
64 | | function sendValue(address payable recipient, uint256 amount) internal {
65 | | require(address(this).balance >= amount, "Address: insufficient balance");
66 | |
67 | | (bool success, ) = recipient.call{value: amount}("");
68 | | require(success, "Address: unable to send value, recipient may have reverted");
69 | | }
70 | |
71 | | /**
72 | | * @dev Performs a Solidity function call using a low level `call`. A
73 | | * plain `call` is an unsafe replacement for a function call: use this
74 | | * function instead.
75 | | *
76 | | * If `target` reverts with a revert reason, it is bubbled up by this
77 | | * function (like regular Solidity function calls).
78 | | *
79 | | * Returns the raw returned data. To convert to the expected return value,
80 | | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
81 | | *
82 | | * Requirements:
83 | | *
84 | | * - `target` must be a contract.
85 | | * - calling `target` with `data` must not revert.
86 | | *
87 | | * _Available since v3.1._
88 | | */
89 | | function functionCall(address target, bytes memory data) internal returns (bytes memory) {
90 | | return functionCallWithValue(target, data, 0, "Address: low-level call failed");
91 | | }
92 | |
93 | | /**
94 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
95 | | * `errorMessage` as a fallback revert reason when `target` reverts.
96 | | *
97 | | * _Available since v3.1._
98 | | */
99 | * | function functionCall(
100 | | address target,
101 | | bytes memory data,
102 | | string memory errorMessage
103 | * | ) internal returns (bytes memory) {
104 | * | return functionCallWithValue(target, data, 0, errorMessage);
105 | | }
106 | |
107 | | /**
108 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
109 | | * but also transferring `value` wei to `target`.
110 | | *
111 | | * Requirements:
112 | | *
113 | | * - the calling contract must have an ETH balance of at least `value`.
114 | | * - the called Solidity function must be `payable`.
115 | | *
116 | | * _Available since v3.1._
117 | | */
118 | | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
119 | | return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
120 | | }
121 | |
122 | | /**
123 | | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
124 | | * with `errorMessage` as a fallback revert reason when `target` reverts.
125 | | *
126 | | * _Available since v3.1._
127 | | */
128 | * | function functionCallWithValue(
129 | | address target,
130 | | bytes memory data,
131 | | uint256 value,
132 | | string memory errorMessage
133 | * | ) internal returns (bytes memory) {
134 | * | require(address(this).balance >= value, "Address: insufficient balance for call");
135 | * | (bool success, bytes memory returndata) = target.call{value: value}(data);
136 | * | return verifyCallResultFromTarget(target, success, returndata, errorMessage);
137 | | }
138 | |
139 | | /**
140 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
141 | | * but performing a static call.
142 | | *
143 | | * _Available since v3.3._
144 | | */
145 | | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
146 | | return functionStaticCall(target, data, "Address: low-level static call failed");
147 | | }
148 | |
149 | | /**
150 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
151 | | * but performing a static call.
152 | | *
153 | | * _Available since v3.3._
154 | | */
155 | | function functionStaticCall(
156 | | address target,
157 | | bytes memory data,
158 | | string memory errorMessage
159 | | ) internal view returns (bytes memory) {
160 | | (bool success, bytes memory returndata) = target.staticcall(data);
161 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage);
162 | | }
163 | |
164 | | /**
165 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
166 | | * but performing a delegate call.
167 | | *
168 | | * _Available since v3.4._
169 | | */
170 | | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
171 | | return functionDelegateCall(target, data, "Address: low-level delegate call failed");
172 | | }
173 | |
174 | | /**
175 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
176 | | * but performing a delegate call.
177 | | *
178 | | * _Available since v3.4._
179 | | */
180 | | function functionDelegateCall(
181 | | address target,
182 | | bytes memory data,
183 | | string memory errorMessage
184 | | ) internal returns (bytes memory) {
185 | | (bool success, bytes memory returndata) = target.delegatecall(data);
186 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage);
187 | | }
188 | |
189 | | /**
190 | | * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
191 | | * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
192 | | *
193 | | * _Available since v4.8._
194 | | */
195 | * | function verifyCallResultFromTarget(
196 | | address target,
197 | | bool success,
198 | | bytes memory returndata,
199 | | string memory errorMessage
200 | * | ) internal view returns (bytes memory) {
201 | * | if (success) {
202 | * | if (returndata.length == 0) {
203 | | // only check isContract if the call was successful and the return data is empty
204 | | // otherwise we already know that it was a contract
205 | | require(isContract(target), "Address: call to non-contract");
206 | | }
207 | * | return returndata;
208 | | } else {
209 | * | _revert(returndata, errorMessage);
210 | | }
211 | | }
212 | |
213 | | /**
214 | | * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
215 | | * revert reason or using the provided one.
216 | | *
217 | | * _Available since v4.3._
218 | | */
219 | | function verifyCallResult(
220 | | bool success,
221 | | bytes memory returndata,
222 | | string memory errorMessage
223 | | ) internal pure returns (bytes memory) {
224 | | if (success) {
225 | | return returndata;
226 | | } else {
227 | | _revert(returndata, errorMessage);
228 | | }
229 | | }
230 | |
231 | * | function _revert(bytes memory returndata, string memory errorMessage) private pure {
232 | | // Look for revert reason and bubble it up if present
233 | * | if (returndata.length > 0) {
234 | | // The easiest way to bubble the revert reason is using memory via assembly
235 | | /// @solidity memory-safe-assembly
236 | | assembly {
237 | * | let returndata_size := mload(returndata)
238 | * | revert(add(32, returndata), returndata_size)
239 | | }
240 | | } else {
241 | | revert(errorMessage);
242 | | }
243 | | }
244 | | }
245 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Checkpoints.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Checkpoints.sol)
3 | | // This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
4 | |
5 | | pragma solidity ^0.8.0;
6 | |
7 | | import "./math/Math.sol";
8 | | import "./math/SafeCast.sol";
9 | |
10 | | /**
11 | | * @dev This library defines the `History` struct, for checkpointing values as they change at different points in
12 | | * time, and later looking up past values by block number. See {Votes} as an example.
13 | | *
14 | | * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
15 | | * checkpoint for the current transaction block using the {push} function.
16 | | *
17 | | * _Available since v4.5._
18 | | */
19 | * | library Checkpoints {
20 | | struct History {
21 | | Checkpoint[] _checkpoints;
22 | | }
23 | |
24 | | struct Checkpoint {
25 | | uint32 _blockNumber;
26 | | uint224 _value;
27 | | }
28 | |
29 | | /**
30 | | * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
31 | | * before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
32 | | * block, the requested block number must be in the past, excluding the current block.
33 | | */
34 | | function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
35 | | require(blockNumber < block.number, "Checkpoints: block not yet mined");
36 | | uint32 key = SafeCast.toUint32(blockNumber);
37 | |
38 | | uint256 len = self._checkpoints.length;
39 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
40 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
41 | | }
42 | |
43 | | /**
44 | | * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
45 | | * before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
46 | | * checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
47 | | * checkpoints.
48 | | */
49 | | function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
50 | | require(blockNumber < block.number, "Checkpoints: block not yet mined");
51 | | uint32 key = SafeCast.toUint32(blockNumber);
52 | |
53 | | uint256 len = self._checkpoints.length;
54 | |
55 | | uint256 low = 0;
56 | | uint256 high = len;
57 | |
58 | | if (len > 5) {
59 | | uint256 mid = len - Math.sqrt(len);
60 | | if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) {
61 | | high = mid;
62 | | } else {
63 | | low = mid + 1;
64 | | }
65 | | }
66 | |
67 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
68 | |
69 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
70 | | }
71 | |
72 | | /**
73 | | * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
74 | | *
75 | | * Returns previous value and new value.
76 | | */
77 | | function push(History storage self, uint256 value) internal returns (uint256, uint256) {
78 | | return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
79 | | }
80 | |
81 | | /**
82 | | * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
83 | | * be set to `op(latest, delta)`.
84 | | *
85 | | * Returns previous value and new value.
86 | | */
87 | | function push(
88 | | History storage self,
89 | | function(uint256, uint256) view returns (uint256) op,
90 | | uint256 delta
91 | | ) internal returns (uint256, uint256) {
92 | | return push(self, op(latest(self), delta));
93 | | }
94 | |
95 | | /**
96 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
97 | | */
98 | | function latest(History storage self) internal view returns (uint224) {
99 | | uint256 pos = self._checkpoints.length;
100 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
101 | | }
102 | |
103 | | /**
104 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
105 | | * in the most recent checkpoint.
106 | | */
107 | | function latestCheckpoint(
108 | | History storage self
109 | | ) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
110 | | uint256 pos = self._checkpoints.length;
111 | | if (pos == 0) {
112 | | return (false, 0, 0);
113 | | } else {
114 | | Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
115 | | return (true, ckpt._blockNumber, ckpt._value);
116 | | }
117 | | }
118 | |
119 | | /**
120 | | * @dev Returns the number of checkpoint.
121 | | */
122 | | function length(History storage self) internal view returns (uint256) {
123 | | return self._checkpoints.length;
124 | | }
125 | |
126 | | /**
127 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
128 | | * or by updating the last one.
129 | | */
130 | | function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
131 | | uint256 pos = self.length;
132 | |
133 | | if (pos > 0) {
134 | | // Copying to memory is important here.
135 | | Checkpoint memory last = _unsafeAccess(self, pos - 1);
136 | |
137 | | // Checkpoint keys must be non-decreasing.
138 | | require(last._blockNumber <= key, "Checkpoint: decreasing keys");
139 | |
140 | | // Update or push new checkpoint
141 | | if (last._blockNumber == key) {
142 | | _unsafeAccess(self, pos - 1)._value = value;
143 | | } else {
144 | | self.push(Checkpoint({_blockNumber: key, _value: value}));
145 | | }
146 | | return (last._value, value);
147 | | } else {
148 | | self.push(Checkpoint({_blockNumber: key, _value: value}));
149 | | return (0, value);
150 | | }
151 | | }
152 | |
153 | | /**
154 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
155 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
156 | | *
157 | | * WARNING: `high` should not be greater than the array's length.
158 | | */
159 | | function _upperBinaryLookup(
160 | | Checkpoint[] storage self,
161 | | uint32 key,
162 | | uint256 low,
163 | | uint256 high
164 | | ) private view returns (uint256) {
165 | | while (low < high) {
166 | | uint256 mid = Math.average(low, high);
167 | | if (_unsafeAccess(self, mid)._blockNumber > key) {
168 | | high = mid;
169 | | } else {
170 | | low = mid + 1;
171 | | }
172 | | }
173 | | return high;
174 | | }
175 | |
176 | | /**
177 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
178 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
179 | | *
180 | | * WARNING: `high` should not be greater than the array's length.
181 | | */
182 | | function _lowerBinaryLookup(
183 | | Checkpoint[] storage self,
184 | | uint32 key,
185 | | uint256 low,
186 | | uint256 high
187 | | ) private view returns (uint256) {
188 | | while (low < high) {
189 | | uint256 mid = Math.average(low, high);
190 | | if (_unsafeAccess(self, mid)._blockNumber < key) {
191 | | low = mid + 1;
192 | | } else {
193 | | high = mid;
194 | | }
195 | | }
196 | | return high;
197 | | }
198 | |
199 | | /**
200 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
201 | | */
202 | | function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
203 | | assembly {
204 | | mstore(0, self.slot)
205 | | result.slot := add(keccak256(0, 0x20), pos)
206 | | }
207 | | }
208 | |
209 | | struct Trace224 {
210 | | Checkpoint224[] _checkpoints;
211 | | }
212 | |
213 | | struct Checkpoint224 {
214 | | uint32 _key;
215 | | uint224 _value;
216 | | }
217 | |
218 | | /**
219 | | * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.
220 | | *
221 | | * Returns previous value and new value.
222 | | */
223 | | function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {
224 | | return _insert(self._checkpoints, key, value);
225 | | }
226 | |
227 | | /**
228 | | * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
229 | | */
230 | | function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
231 | | uint256 len = self._checkpoints.length;
232 | | uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
233 | | return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
234 | | }
235 | |
236 | | /**
237 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
238 | | */
239 | | function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
240 | | uint256 len = self._checkpoints.length;
241 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
242 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
243 | | }
244 | |
245 | | /**
246 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
247 | | *
248 | | * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
249 | | */
250 | | function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {
251 | | uint256 len = self._checkpoints.length;
252 | |
253 | | uint256 low = 0;
254 | | uint256 high = len;
255 | |
256 | | if (len > 5) {
257 | | uint256 mid = len - Math.sqrt(len);
258 | | if (key < _unsafeAccess(self._checkpoints, mid)._key) {
259 | | high = mid;
260 | | } else {
261 | | low = mid + 1;
262 | | }
263 | | }
264 | |
265 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
266 | |
267 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
268 | | }
269 | |
270 | | /**
271 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
272 | | */
273 | | function latest(Trace224 storage self) internal view returns (uint224) {
274 | | uint256 pos = self._checkpoints.length;
275 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
276 | | }
277 | |
278 | | /**
279 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
280 | | * in the most recent checkpoint.
281 | | */
282 | | function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {
283 | | uint256 pos = self._checkpoints.length;
284 | | if (pos == 0) {
285 | | return (false, 0, 0);
286 | | } else {
287 | | Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
288 | | return (true, ckpt._key, ckpt._value);
289 | | }
290 | | }
291 | |
292 | | /**
293 | | * @dev Returns the number of checkpoint.
294 | | */
295 | | function length(Trace224 storage self) internal view returns (uint256) {
296 | | return self._checkpoints.length;
297 | | }
298 | |
299 | | /**
300 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
301 | | * or by updating the last one.
302 | | */
303 | | function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
304 | | uint256 pos = self.length;
305 | |
306 | | if (pos > 0) {
307 | | // Copying to memory is important here.
308 | | Checkpoint224 memory last = _unsafeAccess(self, pos - 1);
309 | |
310 | | // Checkpoint keys must be non-decreasing.
311 | | require(last._key <= key, "Checkpoint: decreasing keys");
312 | |
313 | | // Update or push new checkpoint
314 | | if (last._key == key) {
315 | | _unsafeAccess(self, pos - 1)._value = value;
316 | | } else {
317 | | self.push(Checkpoint224({_key: key, _value: value}));
318 | | }
319 | | return (last._value, value);
320 | | } else {
321 | | self.push(Checkpoint224({_key: key, _value: value}));
322 | | return (0, value);
323 | | }
324 | | }
325 | |
326 | | /**
327 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
328 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
329 | | *
330 | | * WARNING: `high` should not be greater than the array's length.
331 | | */
332 | | function _upperBinaryLookup(
333 | | Checkpoint224[] storage self,
334 | | uint32 key,
335 | | uint256 low,
336 | | uint256 high
337 | | ) private view returns (uint256) {
338 | | while (low < high) {
339 | | uint256 mid = Math.average(low, high);
340 | | if (_unsafeAccess(self, mid)._key > key) {
341 | | high = mid;
342 | | } else {
343 | | low = mid + 1;
344 | | }
345 | | }
346 | | return high;
347 | | }
348 | |
349 | | /**
350 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
351 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
352 | | *
353 | | * WARNING: `high` should not be greater than the array's length.
354 | | */
355 | | function _lowerBinaryLookup(
356 | | Checkpoint224[] storage self,
357 | | uint32 key,
358 | | uint256 low,
359 | | uint256 high
360 | | ) private view returns (uint256) {
361 | | while (low < high) {
362 | | uint256 mid = Math.average(low, high);
363 | | if (_unsafeAccess(self, mid)._key < key) {
364 | | low = mid + 1;
365 | | } else {
366 | | high = mid;
367 | | }
368 | | }
369 | | return high;
370 | | }
371 | |
372 | | /**
373 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
374 | | */
375 | | function _unsafeAccess(
376 | | Checkpoint224[] storage self,
377 | | uint256 pos
378 | | ) private pure returns (Checkpoint224 storage result) {
379 | | assembly {
380 | | mstore(0, self.slot)
381 | | result.slot := add(keccak256(0, 0x20), pos)
382 | | }
383 | | }
384 | |
385 | | struct Trace160 {
386 | | Checkpoint160[] _checkpoints;
387 | | }
388 | |
389 | | struct Checkpoint160 {
390 | | uint96 _key;
391 | | uint160 _value;
392 | | }
393 | |
394 | | /**
395 | | * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.
396 | | *
397 | | * Returns previous value and new value.
398 | | */
399 | | function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {
400 | | return _insert(self._checkpoints, key, value);
401 | | }
402 | |
403 | | /**
404 | | * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
405 | | */
406 | | function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
407 | | uint256 len = self._checkpoints.length;
408 | | uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
409 | | return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
410 | | }
411 | |
412 | | /**
413 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
414 | | */
415 | | function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
416 | | uint256 len = self._checkpoints.length;
417 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
418 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
419 | | }
420 | |
421 | | /**
422 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
423 | | *
424 | | * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
425 | | */
426 | | function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {
427 | | uint256 len = self._checkpoints.length;
428 | |
429 | | uint256 low = 0;
430 | | uint256 high = len;
431 | |
432 | | if (len > 5) {
433 | | uint256 mid = len - Math.sqrt(len);
434 | | if (key < _unsafeAccess(self._checkpoints, mid)._key) {
435 | | high = mid;
436 | | } else {
437 | | low = mid + 1;
438 | | }
439 | | }
440 | |
441 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
442 | |
443 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
444 | | }
445 | |
446 | | /**
447 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
448 | | */
449 | | function latest(Trace160 storage self) internal view returns (uint160) {
450 | | uint256 pos = self._checkpoints.length;
451 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
452 | | }
453 | |
454 | | /**
455 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
456 | | * in the most recent checkpoint.
457 | | */
458 | | function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {
459 | | uint256 pos = self._checkpoints.length;
460 | | if (pos == 0) {
461 | | return (false, 0, 0);
462 | | } else {
463 | | Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
464 | | return (true, ckpt._key, ckpt._value);
465 | | }
466 | | }
467 | |
468 | | /**
469 | | * @dev Returns the number of checkpoint.
470 | | */
471 | | function length(Trace160 storage self) internal view returns (uint256) {
472 | | return self._checkpoints.length;
473 | | }
474 | |
475 | | /**
476 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
477 | | * or by updating the last one.
478 | | */
479 | | function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) {
480 | | uint256 pos = self.length;
481 | |
482 | | if (pos > 0) {
483 | | // Copying to memory is important here.
484 | | Checkpoint160 memory last = _unsafeAccess(self, pos - 1);
485 | |
486 | | // Checkpoint keys must be non-decreasing.
487 | | require(last._key <= key, "Checkpoint: decreasing keys");
488 | |
489 | | // Update or push new checkpoint
490 | | if (last._key == key) {
491 | | _unsafeAccess(self, pos - 1)._value = value;
492 | | } else {
493 | | self.push(Checkpoint160({_key: key, _value: value}));
494 | | }
495 | | return (last._value, value);
496 | | } else {
497 | | self.push(Checkpoint160({_key: key, _value: value}));
498 | | return (0, value);
499 | | }
500 | | }
501 | |
502 | | /**
503 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
504 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
505 | | *
506 | | * WARNING: `high` should not be greater than the array's length.
507 | | */
508 | | function _upperBinaryLookup(
509 | | Checkpoint160[] storage self,
510 | | uint96 key,
511 | | uint256 low,
512 | | uint256 high
513 | | ) private view returns (uint256) {
514 | | while (low < high) {
515 | | uint256 mid = Math.average(low, high);
516 | | if (_unsafeAccess(self, mid)._key > key) {
517 | | high = mid;
518 | | } else {
519 | | low = mid + 1;
520 | | }
521 | | }
522 | | return high;
523 | | }
524 | |
525 | | /**
526 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
527 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
528 | | *
529 | | * WARNING: `high` should not be greater than the array's length.
530 | | */
531 | | function _lowerBinaryLookup(
532 | | Checkpoint160[] storage self,
533 | | uint96 key,
534 | | uint256 low,
535 | | uint256 high
536 | | ) private view returns (uint256) {
537 | | while (low < high) {
538 | | uint256 mid = Math.average(low, high);
539 | | if (_unsafeAccess(self, mid)._key < key) {
540 | | low = mid + 1;
541 | | } else {
542 | | high = mid;
543 | | }
544 | | }
545 | | return high;
546 | | }
547 | |
548 | | /**
549 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
550 | | */
551 | | function _unsafeAccess(
552 | | Checkpoint160[] storage self,
553 | | uint256 pos
554 | | ) private pure returns (Checkpoint160 storage result) {
555 | | assembly {
556 | | mstore(0, self.slot)
557 | | result.slot := add(keccak256(0, 0x20), pos)
558 | | }
559 | | }
560 | | }
561 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Context.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Provides information about the current execution context, including the
8 | | * sender of the transaction and its data. While these are generally available
9 | | * via msg.sender and msg.data, they should not be accessed in such a direct
10 | | * manner, since when dealing with meta-transactions the account sending and
11 | | * paying for execution may not be the actual sender (as far as an application
12 | | * is concerned).
13 | | *
14 | | * This contract is only required for intermediate, library-like contracts.
15 | | */
16 | | abstract contract Context {
17 | * | function _msgSender() internal view virtual returns (address) {
18 | * | return msg.sender;
19 | | }
20 | |
21 | | function _msgData() internal view virtual returns (bytes calldata) {
22 | | return msg.data;
23 | | }
24 | | }
25 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Counters.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @title Counters
8 | | * @author Matt Condon (@shrugs)
9 | | * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
10 | | * of elements in a mapping, issuing ERC721 ids, or counting request ids.
11 | | *
12 | | * Include with `using Counters for Counters.Counter;`
13 | | */
14 | * | library Counters {
15 | | struct Counter {
16 | | // This variable should never be directly accessed by users of the library: interactions must be restricted to
17 | | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
18 | | // this feature: see https://github.com/ethereum/solidity/issues/4637
19 | | uint256 _value; // default: 0
20 | | }
21 | |
22 | | function current(Counter storage counter) internal view returns (uint256) {
23 | | return counter._value;
24 | | }
25 | |
26 | | function increment(Counter storage counter) internal {
27 | | unchecked {
28 | | counter._value += 1;
29 | | }
30 | | }
31 | |
32 | | function decrement(Counter storage counter) internal {
33 | | uint256 value = counter._value;
34 | | require(value > 0, "Counter: decrement overflow");
35 | | unchecked {
36 | | counter._value = value - 1;
37 | | }
38 | | }
39 | |
40 | | function reset(Counter storage counter) internal {
41 | | counter._value = 0;
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/ShortStrings.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)
3 | |
4 | | pragma solidity ^0.8.8;
5 | |
6 | | import "./StorageSlot.sol";
7 | |
8 | | // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
9 | | // | length | 0x BB |
10 | | type ShortString is bytes32;
11 | |
12 | | /**
13 | | * @dev This library provides functions to convert short memory strings
14 | | * into a `ShortString` type that can be used as an immutable variable.
15 | | *
16 | | * Strings of arbitrary length can be optimized using this library if
17 | | * they are short enough (up to 31 bytes) by packing them with their
18 | | * length (1 byte) in a single EVM word (32 bytes). Additionally, a
19 | | * fallback mechanism can be used for every other case.
20 | | *
21 | | * Usage example:
22 | | *
23 | | * ```solidity
24 | | * contract Named {
25 | | * using ShortStrings for *;
26 | | *
27 | | * ShortString private immutable _name;
28 | | * string private _nameFallback;
29 | | *
30 | | * constructor(string memory contractName) {
31 | | * _name = contractName.toShortStringWithFallback(_nameFallback);
32 | | * }
33 | | *
34 | | * function name() external view returns (string memory) {
35 | | * return _name.toStringWithFallback(_nameFallback);
36 | | * }
37 | | * }
38 | | * ```
39 | | */
40 | * | library ShortStrings {
41 | | // Used as an identifier for strings longer than 31 bytes.
42 | | bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;
43 | |
44 | | error StringTooLong(string str);
45 | | error InvalidShortString();
46 | |
47 | | /**
48 | | * @dev Encode a string of at most 31 chars into a `ShortString`.
49 | | *
50 | | * This will trigger a `StringTooLong` error is the input string is too long.
51 | | */
52 | | function toShortString(string memory str) internal pure returns (ShortString) {
53 | | bytes memory bstr = bytes(str);
54 | | if (bstr.length > 31) {
55 | | revert StringTooLong(str);
56 | | }
57 | | return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
58 | | }
59 | |
60 | | /**
61 | | * @dev Decode a `ShortString` back to a "normal" string.
62 | | */
63 | | function toString(ShortString sstr) internal pure returns (string memory) {
64 | | uint256 len = byteLength(sstr);
65 | | // using `new string(len)` would work locally but is not memory safe.
66 | | string memory str = new string(32);
67 | | /// @solidity memory-safe-assembly
68 | | assembly {
69 | | mstore(str, len)
70 | | mstore(add(str, 0x20), sstr)
71 | | }
72 | | return str;
73 | | }
74 | |
75 | | /**
76 | | * @dev Return the length of a `ShortString`.
77 | | */
78 | | function byteLength(ShortString sstr) internal pure returns (uint256) {
79 | | uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
80 | | if (result > 31) {
81 | | revert InvalidShortString();
82 | | }
83 | | return result;
84 | | }
85 | |
86 | | /**
87 | | * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
88 | | */
89 | | function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
90 | | if (bytes(value).length < 32) {
91 | | return toShortString(value);
92 | | } else {
93 | | StorageSlot.getStringSlot(store).value = value;
94 | | return ShortString.wrap(_FALLBACK_SENTINEL);
95 | | }
96 | | }
97 | |
98 | | /**
99 | | * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
100 | | */
101 | | function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
102 | | if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
103 | | return toString(value);
104 | | } else {
105 | | return store;
106 | | }
107 | | }
108 | |
109 | | /**
110 | | * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
111 | | *
112 | | * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
113 | | * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
114 | | */
115 | | function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
116 | | if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
117 | | return byteLength(value);
118 | | } else {
119 | | return bytes(store).length;
120 | | }
121 | | }
122 | | }
123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/StorageSlot.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
3 | | // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
4 | |
5 | | pragma solidity ^0.8.0;
6 | |
7 | | /**
8 | | * @dev Library for reading and writing primitive types to specific storage slots.
9 | | *
10 | | * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
11 | | * This library helps with reading and writing to such slots without the need for inline assembly.
12 | | *
13 | | * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
14 | | *
15 | | * Example usage to set ERC1967 implementation slot:
16 | | * ```solidity
17 | | * contract ERC1967 {
18 | | * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
19 | | *
20 | | * function _getImplementation() internal view returns (address) {
21 | | * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
22 | | * }
23 | | *
24 | | * function _setImplementation(address newImplementation) internal {
25 | | * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
26 | | * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
27 | | * }
28 | | * }
29 | | * ```
30 | | *
31 | | * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
32 | | * _Available since v4.9 for `string`, `bytes`._
33 | | */
34 | * | library StorageSlot {
35 | | struct AddressSlot {
36 | | address value;
37 | | }
38 | |
39 | | struct BooleanSlot {
40 | | bool value;
41 | | }
42 | |
43 | | struct Bytes32Slot {
44 | | bytes32 value;
45 | | }
46 | |
47 | | struct Uint256Slot {
48 | | uint256 value;
49 | | }
50 | |
51 | | struct StringSlot {
52 | | string value;
53 | | }
54 | |
55 | | struct BytesSlot {
56 | | bytes value;
57 | | }
58 | |
59 | | /**
60 | | * @dev Returns an `AddressSlot` with member `value` located at `slot`.
61 | | */
62 | * | function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
63 | | /// @solidity memory-safe-assembly
64 | | assembly {
65 | * | r.slot := slot
66 | | }
67 | | }
68 | |
69 | | /**
70 | | * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
71 | | */
72 | | function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
73 | | /// @solidity memory-safe-assembly
74 | | assembly {
75 | | r.slot := slot
76 | | }
77 | | }
78 | |
79 | | /**
80 | | * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
81 | | */
82 | | function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
83 | | /// @solidity memory-safe-assembly
84 | | assembly {
85 | | r.slot := slot
86 | | }
87 | | }
88 | |
89 | | /**
90 | | * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
91 | | */
92 | | function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
93 | | /// @solidity memory-safe-assembly
94 | | assembly {
95 | | r.slot := slot
96 | | }
97 | | }
98 | |
99 | | /**
100 | | * @dev Returns an `StringSlot` with member `value` located at `slot`.
101 | | */
102 | | function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
103 | | /// @solidity memory-safe-assembly
104 | | assembly {
105 | | r.slot := slot
106 | | }
107 | | }
108 | |
109 | | /**
110 | | * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
111 | | */
112 | | function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
113 | | /// @solidity memory-safe-assembly
114 | | assembly {
115 | | r.slot := store.slot
116 | | }
117 | | }
118 | |
119 | | /**
120 | | * @dev Returns an `BytesSlot` with member `value` located at `slot`.
121 | | */
122 | | function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
123 | | /// @solidity memory-safe-assembly
124 | | assembly {
125 | | r.slot := slot
126 | | }
127 | | }
128 | |
129 | | /**
130 | | * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
131 | | */
132 | | function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
133 | | /// @solidity memory-safe-assembly
134 | | assembly {
135 | | r.slot := store.slot
136 | | }
137 | | }
138 | | }
139 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Strings.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./math/Math.sol";
7 | | import "./math/SignedMath.sol";
8 | |
9 | | /**
10 | | * @dev String operations.
11 | | */
12 | * | library Strings {
13 | | bytes16 private constant _SYMBOLS = "0123456789abcdef";
14 | | uint8 private constant _ADDRESS_LENGTH = 20;
15 | |
16 | | /**
17 | | * @dev Converts a `uint256` to its ASCII `string` decimal representation.
18 | | */
19 | | function toString(uint256 value) internal pure returns (string memory) {
20 | | unchecked {
21 | | uint256 length = Math.log10(value) + 1;
22 | | string memory buffer = new string(length);
23 | | uint256 ptr;
24 | | /// @solidity memory-safe-assembly
25 | | assembly {
26 | | ptr := add(buffer, add(32, length))
27 | | }
28 | | while (true) {
29 | | ptr--;
30 | | /// @solidity memory-safe-assembly
31 | | assembly {
32 | | mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
33 | | }
34 | | value /= 10;
35 | | if (value == 0) break;
36 | | }
37 | | return buffer;
38 | | }
39 | | }
40 | |
41 | | /**
42 | | * @dev Converts a `int256` to its ASCII `string` decimal representation.
43 | | */
44 | | function toString(int256 value) internal pure returns (string memory) {
45 | | return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
46 | | }
47 | |
48 | | /**
49 | | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
50 | | */
51 | | function toHexString(uint256 value) internal pure returns (string memory) {
52 | | unchecked {
53 | | return toHexString(value, Math.log256(value) + 1);
54 | | }
55 | | }
56 | |
57 | | /**
58 | | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
59 | | */
60 | | function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
61 | | bytes memory buffer = new bytes(2 * length + 2);
62 | | buffer[0] = "0";
63 | | buffer[1] = "x";
64 | | for (uint256 i = 2 * length + 1; i > 1; --i) {
65 | | buffer[i] = _SYMBOLS[value & 0xf];
66 | | value >>= 4;
67 | | }
68 | | require(value == 0, "Strings: hex length insufficient");
69 | | return string(buffer);
70 | | }
71 | |
72 | | /**
73 | | * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
74 | | */
75 | | function toHexString(address addr) internal pure returns (string memory) {
76 | | return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
77 | | }
78 | |
79 | | /**
80 | | * @dev Returns true if the two strings are equal.
81 | | */
82 | | function equal(string memory a, string memory b) internal pure returns (bool) {
83 | | return keccak256(bytes(a)) == keccak256(bytes(b));
84 | | }
85 | | }
86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../Strings.sol";
7 | |
8 | | /**
9 | | * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
10 | | *
11 | | * These functions can be used to verify that a message was signed by the holder
12 | | * of the private keys of a given address.
13 | | */
14 | * | library ECDSA {
15 | | enum RecoverError {
16 | | NoError,
17 | | InvalidSignature,
18 | | InvalidSignatureLength,
19 | | InvalidSignatureS,
20 | | InvalidSignatureV // Deprecated in v4.8
21 | | }
22 | |
23 | | function _throwError(RecoverError error) private pure {
24 | | if (error == RecoverError.NoError) {
25 | | return; // no error: do nothing
26 | | } else if (error == RecoverError.InvalidSignature) {
27 | | revert("ECDSA: invalid signature");
28 | | } else if (error == RecoverError.InvalidSignatureLength) {
29 | | revert("ECDSA: invalid signature length");
30 | | } else if (error == RecoverError.InvalidSignatureS) {
31 | | revert("ECDSA: invalid signature 's' value");
32 | | }
33 | | }
34 | |
35 | | /**
36 | | * @dev Returns the address that signed a hashed message (`hash`) with
37 | | * `signature` or error string. This address can then be used for verification purposes.
38 | | *
39 | | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
40 | | * this function rejects them by requiring the `s` value to be in the lower
41 | | * half order, and the `v` value to be either 27 or 28.
42 | | *
43 | | * IMPORTANT: `hash` _must_ be the result of a hash operation for the
44 | | * verification to be secure: it is possible to craft signatures that
45 | | * recover to arbitrary addresses for non-hashed data. A safe way to ensure
46 | | * this is by receiving a hash of the original message (which may otherwise
47 | | * be too long), and then calling {toEthSignedMessageHash} on it.
48 | | *
49 | | * Documentation for signature generation:
50 | | * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
51 | | * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
52 | | *
53 | | * _Available since v4.3._
54 | | */
55 | | function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
56 | | if (signature.length == 65) {
57 | | bytes32 r;
58 | | bytes32 s;
59 | | uint8 v;
60 | | // ecrecover takes the signature parameters, and the only way to get them
61 | | // currently is to use assembly.
62 | | /// @solidity memory-safe-assembly
63 | | assembly {
64 | | r := mload(add(signature, 0x20))
65 | | s := mload(add(signature, 0x40))
66 | | v := byte(0, mload(add(signature, 0x60)))
67 | | }
68 | | return tryRecover(hash, v, r, s);
69 | | } else {
70 | | return (address(0), RecoverError.InvalidSignatureLength);
71 | | }
72 | | }
73 | |
74 | | /**
75 | | * @dev Returns the address that signed a hashed message (`hash`) with
76 | | * `signature`. This address can then be used for verification purposes.
77 | | *
78 | | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
79 | | * this function rejects them by requiring the `s` value to be in the lower
80 | | * half order, and the `v` value to be either 27 or 28.
81 | | *
82 | | * IMPORTANT: `hash` _must_ be the result of a hash operation for the
83 | | * verification to be secure: it is possible to craft signatures that
84 | | * recover to arbitrary addresses for non-hashed data. A safe way to ensure
85 | | * this is by receiving a hash of the original message (which may otherwise
86 | | * be too long), and then calling {toEthSignedMessageHash} on it.
87 | | */
88 | | function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
89 | | (address recovered, RecoverError error) = tryRecover(hash, signature);
90 | | _throwError(error);
91 | | return recovered;
92 | | }
93 | |
94 | | /**
95 | | * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
96 | | *
97 | | * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
98 | | *
99 | | * _Available since v4.3._
100 | | */
101 | | function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
102 | | bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
103 | | uint8 v = uint8((uint256(vs) >> 255) + 27);
104 | | return tryRecover(hash, v, r, s);
105 | | }
106 | |
107 | | /**
108 | | * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
109 | | *
110 | | * _Available since v4.2._
111 | | */
112 | | function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
113 | | (address recovered, RecoverError error) = tryRecover(hash, r, vs);
114 | | _throwError(error);
115 | | return recovered;
116 | | }
117 | |
118 | | /**
119 | | * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
120 | | * `r` and `s` signature fields separately.
121 | | *
122 | | * _Available since v4.3._
123 | | */
124 | | function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
125 | | // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
126 | | // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
127 | | // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
128 | | // signatures from current libraries generate a unique signature with an s-value in the lower half order.
129 | | //
130 | | // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
131 | | // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
132 | | // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
133 | | // these malleable signatures as well.
134 | | if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
135 | | return (address(0), RecoverError.InvalidSignatureS);
136 | | }
137 | |
138 | | // If the signature is valid (and not malleable), return the signer address
139 | | address signer = ecrecover(hash, v, r, s);
140 | | if (signer == address(0)) {
141 | | return (address(0), RecoverError.InvalidSignature);
142 | | }
143 | |
144 | | return (signer, RecoverError.NoError);
145 | | }
146 | |
147 | | /**
148 | | * @dev Overload of {ECDSA-recover} that receives the `v`,
149 | | * `r` and `s` signature fields separately.
150 | | */
151 | | function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
152 | | (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
153 | | _throwError(error);
154 | | return recovered;
155 | | }
156 | |
157 | | /**
158 | | * @dev Returns an Ethereum Signed Message, created from a `hash`. This
159 | | * produces hash corresponding to the one signed with the
160 | | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
161 | | * JSON-RPC method as part of EIP-191.
162 | | *
163 | | * See {recover}.
164 | | */
165 | | function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
166 | | // 32 is the length in bytes of hash,
167 | | // enforced by the type signature above
168 | | /// @solidity memory-safe-assembly
169 | | assembly {
170 | | mstore(0x00, "\x19Ethereum Signed Message:\n32")
171 | | mstore(0x1c, hash)
172 | | message := keccak256(0x00, 0x3c)
173 | | }
174 | | }
175 | |
176 | | /**
177 | | * @dev Returns an Ethereum Signed Message, created from `s`. This
178 | | * produces hash corresponding to the one signed with the
179 | | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
180 | | * JSON-RPC method as part of EIP-191.
181 | | *
182 | | * See {recover}.
183 | | */
184 | | function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
185 | | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
186 | | }
187 | |
188 | | /**
189 | | * @dev Returns an Ethereum Signed Typed Data, created from a
190 | | * `domainSeparator` and a `structHash`. This produces hash corresponding
191 | | * to the one signed with the
192 | | * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
193 | | * JSON-RPC method as part of EIP-712.
194 | | *
195 | | * See {recover}.
196 | | */
197 | | function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
198 | | /// @solidity memory-safe-assembly
199 | | assembly {
200 | | let ptr := mload(0x40)
201 | | mstore(ptr, "\x19\x01")
202 | | mstore(add(ptr, 0x02), domainSeparator)
203 | | mstore(add(ptr, 0x22), structHash)
204 | | data := keccak256(ptr, 0x42)
205 | | }
206 | | }
207 | |
208 | | /**
209 | | * @dev Returns an Ethereum Signed Data with intended validator, created from a
210 | | * `validator` and `data` according to the version 0 of EIP-191.
211 | | *
212 | | * See {recover}.
213 | | */
214 | | function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
215 | | return keccak256(abi.encodePacked("\x19\x00", validator, data));
216 | | }
217 | | }
218 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)
3 | |
4 | | pragma solidity ^0.8.8;
5 | |
6 | | import "./ECDSA.sol";
7 | | import "../ShortStrings.sol";
8 | | import "../../interfaces/IERC5267.sol";
9 | |
10 | | /**
11 | | * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
12 | | *
13 | | * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
14 | | * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
15 | | * they need in their contracts using a combination of `abi.encode` and `keccak256`.
16 | | *
17 | | * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
18 | | * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
19 | | * ({_hashTypedDataV4}).
20 | | *
21 | | * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
22 | | * the chain id to protect against replay attacks on an eventual fork of the chain.
23 | | *
24 | | * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
25 | | * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
26 | | *
27 | | * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
28 | | * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
29 | | * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
30 | | *
31 | | * _Available since v3.4._
32 | | *
33 | | * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
34 | | */
35 | | abstract contract EIP712 is IERC5267 {
36 | | using ShortStrings for *;
37 | |
38 | | bytes32 private constant _TYPE_HASH =
39 | | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
40 | |
41 | | // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
42 | | // invalidate the cached domain separator if the chain id changes.
43 | | bytes32 private immutable _cachedDomainSeparator;
44 | | uint256 private immutable _cachedChainId;
45 | | address private immutable _cachedThis;
46 | |
47 | | bytes32 private immutable _hashedName;
48 | | bytes32 private immutable _hashedVersion;
49 | |
50 | | ShortString private immutable _name;
51 | | ShortString private immutable _version;
52 | | string private _nameFallback;
53 | | string private _versionFallback;
54 | |
55 | | /**
56 | | * @dev Initializes the domain separator and parameter caches.
57 | | *
58 | | * The meaning of `name` and `version` is specified in
59 | | * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
60 | | *
61 | | * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
62 | | * - `version`: the current major version of the signing domain.
63 | | *
64 | | * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
65 | | * contract upgrade].
66 | | */
67 | | constructor(string memory name, string memory version) {
68 | | _name = name.toShortStringWithFallback(_nameFallback);
69 | | _version = version.toShortStringWithFallback(_versionFallback);
70 | | _hashedName = keccak256(bytes(name));
71 | | _hashedVersion = keccak256(bytes(version));
72 | |
73 | | _cachedChainId = block.chainid;
74 | | _cachedDomainSeparator = _buildDomainSeparator();
75 | | _cachedThis = address(this);
76 | | }
77 | |
78 | | /**
79 | | * @dev Returns the domain separator for the current chain.
80 | | */
81 | | function _domainSeparatorV4() internal view returns (bytes32) {
82 | | if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
83 | | return _cachedDomainSeparator;
84 | | } else {
85 | | return _buildDomainSeparator();
86 | | }
87 | | }
88 | |
89 | | function _buildDomainSeparator() private view returns (bytes32) {
90 | | return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
91 | | }
92 | |
93 | | /**
94 | | * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
95 | | * function returns the hash of the fully encoded EIP712 message for this domain.
96 | | *
97 | | * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
98 | | *
99 | | * ```solidity
100 | | * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
101 | | * keccak256("Mail(address to,string contents)"),
102 | | * mailTo,
103 | | * keccak256(bytes(mailContents))
104 | | * )));
105 | | * address signer = ECDSA.recover(digest, signature);
106 | | * ```
107 | | */
108 | | function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
109 | | return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
110 | | }
111 | |
112 | | /**
113 | | * @dev See {EIP-5267}.
114 | | *
115 | | * _Available since v4.9._
116 | | */
117 | | function eip712Domain()
118 | | public
119 | | view
120 | | virtual
121 | | override
122 | | returns (
123 | | bytes1 fields,
124 | | string memory name,
125 | | string memory version,
126 | | uint256 chainId,
127 | | address verifyingContract,
128 | | bytes32 salt,
129 | | uint256[] memory extensions
130 | | )
131 | | {
132 | | return (
133 | | hex"0f", // 01111
134 | | _name.toStringWithFallback(_nameFallback),
135 | | _version.toStringWithFallback(_versionFallback),
136 | | block.chainid,
137 | | address(this),
138 | | bytes32(0),
139 | | new uint256[](0)
140 | | );
141 | | }
142 | | }
143 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "./IERC165.sol";
7 | |
8 | | /**
9 | | * @dev Implementation of the {IERC165} interface.
10 | | *
11 | | * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
12 | | * for the additional interface id that will be supported. For example:
13 | | *
14 | | * ```solidity
15 | | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
16 | | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
17 | | * }
18 | | * ```
19 | | *
20 | | * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
21 | | */
22 | | abstract contract ERC165 is IERC165 {
23 | | /**
24 | | * @dev See {IERC165-supportsInterface}.
25 | | */
26 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
27 | | return interfaceId == type(IERC165).interfaceId;
28 | | }
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Interface of the ERC165 standard, as defined in the
8 | | * https://eips.ethereum.org/EIPS/eip-165[EIP].
9 | | *
10 | | * Implementers can declare support of contract interfaces, which can then be
11 | | * queried by others ({ERC165Checker}).
12 | | *
13 | | * For an implementation, see {ERC165}.
14 | | */
15 | | interface IERC165 {
16 | | /**
17 | | * @dev Returns true if this contract implements the interface defined by
18 | | * `interfaceId`. See the corresponding
19 | | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
20 | | * to learn more about how these ids are created.
21 | | *
22 | | * This function call must use less than 30 000 gas.
23 | | */
24 | | function supportsInterface(bytes4 interfaceId) external view returns (bool);
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/Math.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Standard math utilities missing in the Solidity language.
8 | | */
9 | * | library Math {
10 | | enum Rounding {
11 | | Down, // Toward negative infinity
12 | | Up, // Toward infinity
13 | | Zero // Toward zero
14 | | }
15 | |
16 | | /**
17 | | * @dev Returns the largest of two numbers.
18 | | */
19 | | function max(uint256 a, uint256 b) internal pure returns (uint256) {
20 | | return a > b ? a : b;
21 | | }
22 | |
23 | | /**
24 | | * @dev Returns the smallest of two numbers.
25 | | */
26 | | function min(uint256 a, uint256 b) internal pure returns (uint256) {
27 | | return a < b ? a : b;
28 | | }
29 | |
30 | | /**
31 | | * @dev Returns the average of two numbers. The result is rounded towards
32 | | * zero.
33 | | */
34 | | function average(uint256 a, uint256 b) internal pure returns (uint256) {
35 | | // (a + b) / 2 can overflow.
36 | | return (a & b) + (a ^ b) / 2;
37 | | }
38 | |
39 | | /**
40 | | * @dev Returns the ceiling of the division of two numbers.
41 | | *
42 | | * This differs from standard division with `/` in that it rounds up instead
43 | | * of rounding down.
44 | | */
45 | | function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
46 | | // (a + b - 1) / b can overflow on addition, so we distribute.
47 | | return a == 0 ? 0 : (a - 1) / b + 1;
48 | | }
49 | |
50 | | /**
51 | | * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
52 | | * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
53 | | * with further edits by Uniswap Labs also under MIT license.
54 | | */
55 | * | function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
56 | | unchecked {
57 | | // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
58 | | // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
59 | | // variables such that product = prod1 * 2^256 + prod0.
60 | * | uint256 prod0; // Least significant 256 bits of the product
61 | * | uint256 prod1; // Most significant 256 bits of the product
62 | * | assembly {
63 | * | let mm := mulmod(x, y, not(0))
64 | * | prod0 := mul(x, y)
65 | * | prod1 := sub(sub(mm, prod0), lt(mm, prod0))
66 | | }
67 | |
68 | | // Handle non-overflow cases, 256 by 256 division.
69 | * | if (prod1 == 0) {
70 | | // Solidity will revert if denominator == 0, unlike the div opcode on its own.
71 | | // The surrounding unchecked block does not change this fact.
72 | | // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
73 | * | return prod0 / denominator;
74 | | }
75 | |
76 | | // Make sure the result is less than 2^256. Also prevents denominator == 0.
77 | * | require(denominator > prod1, "Math: mulDiv overflow");
78 | |
79 | | ///////////////////////////////////////////////
80 | | // 512 by 256 division.
81 | | ///////////////////////////////////////////////
82 | |
83 | | // Make division exact by subtracting the remainder from [prod1 prod0].
84 | * | uint256 remainder;
85 | | assembly {
86 | | // Compute remainder using mulmod.
87 | * | remainder := mulmod(x, y, denominator)
88 | |
89 | | // Subtract 256 bit number from 512 bit number.
90 | * | prod1 := sub(prod1, gt(remainder, prod0))
91 | * | prod0 := sub(prod0, remainder)
92 | | }
93 | |
94 | | // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
95 | | // See https://cs.stackexchange.com/q/138556/92363.
96 | |
97 | | // Does not overflow because the denominator cannot be zero at this stage in the function.
98 | * | uint256 twos = denominator & (~denominator + 1);
99 | | assembly {
100 | | // Divide denominator by twos.
101 | * | denominator := div(denominator, twos)
102 | |
103 | | // Divide [prod1 prod0] by twos.
104 | * | prod0 := div(prod0, twos)
105 | |
106 | | // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
107 | * | twos := add(div(sub(0, twos), twos), 1)
108 | | }
109 | |
110 | | // Shift in bits from prod1 into prod0.
111 | * | prod0 |= prod1 * twos;
112 | |
113 | | // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
114 | | // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
115 | | // four bits. That is, denominator * inv = 1 mod 2^4.
116 | * | uint256 inverse = (3 * denominator) ^ 2;
117 | |
118 | | // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
119 | | // in modular arithmetic, doubling the correct bits in each step.
120 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^8
121 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^16
122 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^32
123 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^64
124 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^128
125 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^256
126 | |
127 | | // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
128 | | // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
129 | | // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
130 | | // is no longer required.
131 | * | result = prod0 * inverse;
132 | * | return result;
133 | | }
134 | | }
135 | |
136 | | /**
137 | | * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
138 | | */
139 | * | function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
140 | * | uint256 result = mulDiv(x, y, denominator);
141 | * | if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
142 | * | result += 1;
143 | | }
144 | * | return result;
145 | | }
146 | |
147 | | /**
148 | | * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
149 | | *
150 | | * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
151 | | */
152 | | function sqrt(uint256 a) internal pure returns (uint256) {
153 | | if (a == 0) {
154 | | return 0;
155 | | }
156 | |
157 | | // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
158 | | //
159 | | // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
160 | | // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
161 | | //
162 | | // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
163 | | // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
164 | | // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
165 | | //
166 | | // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
167 | | uint256 result = 1 << (log2(a) >> 1);
168 | |
169 | | // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
170 | | // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
171 | | // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
172 | | // into the expected uint128 result.
173 | | unchecked {
174 | | result = (result + a / result) >> 1;
175 | | result = (result + a / result) >> 1;
176 | | result = (result + a / result) >> 1;
177 | | result = (result + a / result) >> 1;
178 | | result = (result + a / result) >> 1;
179 | | result = (result + a / result) >> 1;
180 | | result = (result + a / result) >> 1;
181 | | return min(result, a / result);
182 | | }
183 | | }
184 | |
185 | | /**
186 | | * @notice Calculates sqrt(a), following the selected rounding direction.
187 | | */
188 | | function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
189 | | unchecked {
190 | | uint256 result = sqrt(a);
191 | | return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
192 | | }
193 | | }
194 | |
195 | | /**
196 | | * @dev Return the log in base 2, rounded down, of a positive value.
197 | | * Returns 0 if given 0.
198 | | */
199 | | function log2(uint256 value) internal pure returns (uint256) {
200 | | uint256 result = 0;
201 | | unchecked {
202 | | if (value >> 128 > 0) {
203 | | value >>= 128;
204 | | result += 128;
205 | | }
206 | | if (value >> 64 > 0) {
207 | | value >>= 64;
208 | | result += 64;
209 | | }
210 | | if (value >> 32 > 0) {
211 | | value >>= 32;
212 | | result += 32;
213 | | }
214 | | if (value >> 16 > 0) {
215 | | value >>= 16;
216 | | result += 16;
217 | | }
218 | | if (value >> 8 > 0) {
219 | | value >>= 8;
220 | | result += 8;
221 | | }
222 | | if (value >> 4 > 0) {
223 | | value >>= 4;
224 | | result += 4;
225 | | }
226 | | if (value >> 2 > 0) {
227 | | value >>= 2;
228 | | result += 2;
229 | | }
230 | | if (value >> 1 > 0) {
231 | | result += 1;
232 | | }
233 | | }
234 | | return result;
235 | | }
236 | |
237 | | /**
238 | | * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
239 | | * Returns 0 if given 0.
240 | | */
241 | | function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
242 | | unchecked {
243 | | uint256 result = log2(value);
244 | | return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
245 | | }
246 | | }
247 | |
248 | | /**
249 | | * @dev Return the log in base 10, rounded down, of a positive value.
250 | | * Returns 0 if given 0.
251 | | */
252 | | function log10(uint256 value) internal pure returns (uint256) {
253 | | uint256 result = 0;
254 | | unchecked {
255 | | if (value >= 10 ** 64) {
256 | | value /= 10 ** 64;
257 | | result += 64;
258 | | }
259 | | if (value >= 10 ** 32) {
260 | | value /= 10 ** 32;
261 | | result += 32;
262 | | }
263 | | if (value >= 10 ** 16) {
264 | | value /= 10 ** 16;
265 | | result += 16;
266 | | }
267 | | if (value >= 10 ** 8) {
268 | | value /= 10 ** 8;
269 | | result += 8;
270 | | }
271 | | if (value >= 10 ** 4) {
272 | | value /= 10 ** 4;
273 | | result += 4;
274 | | }
275 | | if (value >= 10 ** 2) {
276 | | value /= 10 ** 2;
277 | | result += 2;
278 | | }
279 | | if (value >= 10 ** 1) {
280 | | result += 1;
281 | | }
282 | | }
283 | | return result;
284 | | }
285 | |
286 | | /**
287 | | * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
288 | | * Returns 0 if given 0.
289 | | */
290 | | function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
291 | | unchecked {
292 | | uint256 result = log10(value);
293 | | return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
294 | | }
295 | | }
296 | |
297 | | /**
298 | | * @dev Return the log in base 256, rounded down, of a positive value.
299 | | * Returns 0 if given 0.
300 | | *
301 | | * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
302 | | */
303 | | function log256(uint256 value) internal pure returns (uint256) {
304 | | uint256 result = 0;
305 | | unchecked {
306 | | if (value >> 128 > 0) {
307 | | value >>= 128;
308 | | result += 16;
309 | | }
310 | | if (value >> 64 > 0) {
311 | | value >>= 64;
312 | | result += 8;
313 | | }
314 | | if (value >> 32 > 0) {
315 | | value >>= 32;
316 | | result += 4;
317 | | }
318 | | if (value >> 16 > 0) {
319 | | value >>= 16;
320 | | result += 2;
321 | | }
322 | | if (value >> 8 > 0) {
323 | | result += 1;
324 | | }
325 | | }
326 | | return result;
327 | | }
328 | |
329 | | /**
330 | | * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
331 | | * Returns 0 if given 0.
332 | | */
333 | | function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
334 | | unchecked {
335 | | uint256 result = log256(value);
336 | | return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
337 | | }
338 | | }
339 | | }
340 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
3 | | // This file was procedurally generated from scripts/generate/templates/SafeCast.js.
4 | |
5 | | pragma solidity ^0.8.0;
6 | |
7 | | /**
8 | | * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
9 | | * checks.
10 | | *
11 | | * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
12 | | * easily result in undesired exploitation or bugs, since developers usually
13 | | * assume that overflows raise errors. `SafeCast` restores this intuition by
14 | | * reverting the transaction when such an operation overflows.
15 | | *
16 | | * Using this library instead of the unchecked operations eliminates an entire
17 | | * class of bugs, so it's recommended to use it always.
18 | | *
19 | | * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
20 | | * all math on `uint256` and `int256` and then downcasting.
21 | | */
22 | * | library SafeCast {
23 | | /**
24 | | * @dev Returns the downcasted uint248 from uint256, reverting on
25 | | * overflow (when the input is greater than largest uint248).
26 | | *
27 | | * Counterpart to Solidity's `uint248` operator.
28 | | *
29 | | * Requirements:
30 | | *
31 | | * - input must fit into 248 bits
32 | | *
33 | | * _Available since v4.7._
34 | | */
35 | | function toUint248(uint256 value) internal pure returns (uint248) {
36 | | require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
37 | | return uint248(value);
38 | | }
39 | |
40 | | /**
41 | | * @dev Returns the downcasted uint240 from uint256, reverting on
42 | | * overflow (when the input is greater than largest uint240).
43 | | *
44 | | * Counterpart to Solidity's `uint240` operator.
45 | | *
46 | | * Requirements:
47 | | *
48 | | * - input must fit into 240 bits
49 | | *
50 | | * _Available since v4.7._
51 | | */
52 | | function toUint240(uint256 value) internal pure returns (uint240) {
53 | | require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
54 | | return uint240(value);
55 | | }
56 | |
57 | | /**
58 | | * @dev Returns the downcasted uint232 from uint256, reverting on
59 | | * overflow (when the input is greater than largest uint232).
60 | | *
61 | | * Counterpart to Solidity's `uint232` operator.
62 | | *
63 | | * Requirements:
64 | | *
65 | | * - input must fit into 232 bits
66 | | *
67 | | * _Available since v4.7._
68 | | */
69 | | function toUint232(uint256 value) internal pure returns (uint232) {
70 | | require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
71 | | return uint232(value);
72 | | }
73 | |
74 | | /**
75 | | * @dev Returns the downcasted uint224 from uint256, reverting on
76 | | * overflow (when the input is greater than largest uint224).
77 | | *
78 | | * Counterpart to Solidity's `uint224` operator.
79 | | *
80 | | * Requirements:
81 | | *
82 | | * - input must fit into 224 bits
83 | | *
84 | | * _Available since v4.2._
85 | | */
86 | | function toUint224(uint256 value) internal pure returns (uint224) {
87 | | require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
88 | | return uint224(value);
89 | | }
90 | |
91 | | /**
92 | | * @dev Returns the downcasted uint216 from uint256, reverting on
93 | | * overflow (when the input is greater than largest uint216).
94 | | *
95 | | * Counterpart to Solidity's `uint216` operator.
96 | | *
97 | | * Requirements:
98 | | *
99 | | * - input must fit into 216 bits
100 | | *
101 | | * _Available since v4.7._
102 | | */
103 | | function toUint216(uint256 value) internal pure returns (uint216) {
104 | | require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
105 | | return uint216(value);
106 | | }
107 | |
108 | | /**
109 | | * @dev Returns the downcasted uint208 from uint256, reverting on
110 | | * overflow (when the input is greater than largest uint208).
111 | | *
112 | | * Counterpart to Solidity's `uint208` operator.
113 | | *
114 | | * Requirements:
115 | | *
116 | | * - input must fit into 208 bits
117 | | *
118 | | * _Available since v4.7._
119 | | */
120 | | function toUint208(uint256 value) internal pure returns (uint208) {
121 | | require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
122 | | return uint208(value);
123 | | }
124 | |
125 | | /**
126 | | * @dev Returns the downcasted uint200 from uint256, reverting on
127 | | * overflow (when the input is greater than largest uint200).
128 | | *
129 | | * Counterpart to Solidity's `uint200` operator.
130 | | *
131 | | * Requirements:
132 | | *
133 | | * - input must fit into 200 bits
134 | | *
135 | | * _Available since v4.7._
136 | | */
137 | | function toUint200(uint256 value) internal pure returns (uint200) {
138 | | require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
139 | | return uint200(value);
140 | | }
141 | |
142 | | /**
143 | | * @dev Returns the downcasted uint192 from uint256, reverting on
144 | | * overflow (when the input is greater than largest uint192).
145 | | *
146 | | * Counterpart to Solidity's `uint192` operator.
147 | | *
148 | | * Requirements:
149 | | *
150 | | * - input must fit into 192 bits
151 | | *
152 | | * _Available since v4.7._
153 | | */
154 | | function toUint192(uint256 value) internal pure returns (uint192) {
155 | | require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
156 | | return uint192(value);
157 | | }
158 | |
159 | | /**
160 | | * @dev Returns the downcasted uint184 from uint256, reverting on
161 | | * overflow (when the input is greater than largest uint184).
162 | | *
163 | | * Counterpart to Solidity's `uint184` operator.
164 | | *
165 | | * Requirements:
166 | | *
167 | | * - input must fit into 184 bits
168 | | *
169 | | * _Available since v4.7._
170 | | */
171 | | function toUint184(uint256 value) internal pure returns (uint184) {
172 | | require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
173 | | return uint184(value);
174 | | }
175 | |
176 | | /**
177 | | * @dev Returns the downcasted uint176 from uint256, reverting on
178 | | * overflow (when the input is greater than largest uint176).
179 | | *
180 | | * Counterpart to Solidity's `uint176` operator.
181 | | *
182 | | * Requirements:
183 | | *
184 | | * - input must fit into 176 bits
185 | | *
186 | | * _Available since v4.7._
187 | | */
188 | | function toUint176(uint256 value) internal pure returns (uint176) {
189 | | require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
190 | | return uint176(value);
191 | | }
192 | |
193 | | /**
194 | | * @dev Returns the downcasted uint168 from uint256, reverting on
195 | | * overflow (when the input is greater than largest uint168).
196 | | *
197 | | * Counterpart to Solidity's `uint168` operator.
198 | | *
199 | | * Requirements:
200 | | *
201 | | * - input must fit into 168 bits
202 | | *
203 | | * _Available since v4.7._
204 | | */
205 | | function toUint168(uint256 value) internal pure returns (uint168) {
206 | | require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
207 | | return uint168(value);
208 | | }
209 | |
210 | | /**
211 | | * @dev Returns the downcasted uint160 from uint256, reverting on
212 | | * overflow (when the input is greater than largest uint160).
213 | | *
214 | | * Counterpart to Solidity's `uint160` operator.
215 | | *
216 | | * Requirements:
217 | | *
218 | | * - input must fit into 160 bits
219 | | *
220 | | * _Available since v4.7._
221 | | */
222 | | function toUint160(uint256 value) internal pure returns (uint160) {
223 | | require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
224 | | return uint160(value);
225 | | }
226 | |
227 | | /**
228 | | * @dev Returns the downcasted uint152 from uint256, reverting on
229 | | * overflow (when the input is greater than largest uint152).
230 | | *
231 | | * Counterpart to Solidity's `uint152` operator.
232 | | *
233 | | * Requirements:
234 | | *
235 | | * - input must fit into 152 bits
236 | | *
237 | | * _Available since v4.7._
238 | | */
239 | | function toUint152(uint256 value) internal pure returns (uint152) {
240 | | require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
241 | | return uint152(value);
242 | | }
243 | |
244 | | /**
245 | | * @dev Returns the downcasted uint144 from uint256, reverting on
246 | | * overflow (when the input is greater than largest uint144).
247 | | *
248 | | * Counterpart to Solidity's `uint144` operator.
249 | | *
250 | | * Requirements:
251 | | *
252 | | * - input must fit into 144 bits
253 | | *
254 | | * _Available since v4.7._
255 | | */
256 | | function toUint144(uint256 value) internal pure returns (uint144) {
257 | | require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
258 | | return uint144(value);
259 | | }
260 | |
261 | | /**
262 | | * @dev Returns the downcasted uint136 from uint256, reverting on
263 | | * overflow (when the input is greater than largest uint136).
264 | | *
265 | | * Counterpart to Solidity's `uint136` operator.
266 | | *
267 | | * Requirements:
268 | | *
269 | | * - input must fit into 136 bits
270 | | *
271 | | * _Available since v4.7._
272 | | */
273 | | function toUint136(uint256 value) internal pure returns (uint136) {
274 | | require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
275 | | return uint136(value);
276 | | }
277 | |
278 | | /**
279 | | * @dev Returns the downcasted uint128 from uint256, reverting on
280 | | * overflow (when the input is greater than largest uint128).
281 | | *
282 | | * Counterpart to Solidity's `uint128` operator.
283 | | *
284 | | * Requirements:
285 | | *
286 | | * - input must fit into 128 bits
287 | | *
288 | | * _Available since v2.5._
289 | | */
290 | | function toUint128(uint256 value) internal pure returns (uint128) {
291 | | require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
292 | | return uint128(value);
293 | | }
294 | |
295 | | /**
296 | | * @dev Returns the downcasted uint120 from uint256, reverting on
297 | | * overflow (when the input is greater than largest uint120).
298 | | *
299 | | * Counterpart to Solidity's `uint120` operator.
300 | | *
301 | | * Requirements:
302 | | *
303 | | * - input must fit into 120 bits
304 | | *
305 | | * _Available since v4.7._
306 | | */
307 | | function toUint120(uint256 value) internal pure returns (uint120) {
308 | | require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
309 | | return uint120(value);
310 | | }
311 | |
312 | | /**
313 | | * @dev Returns the downcasted uint112 from uint256, reverting on
314 | | * overflow (when the input is greater than largest uint112).
315 | | *
316 | | * Counterpart to Solidity's `uint112` operator.
317 | | *
318 | | * Requirements:
319 | | *
320 | | * - input must fit into 112 bits
321 | | *
322 | | * _Available since v4.7._
323 | | */
324 | | function toUint112(uint256 value) internal pure returns (uint112) {
325 | | require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
326 | | return uint112(value);
327 | | }
328 | |
329 | | /**
330 | | * @dev Returns the downcasted uint104 from uint256, reverting on
331 | | * overflow (when the input is greater than largest uint104).
332 | | *
333 | | * Counterpart to Solidity's `uint104` operator.
334 | | *
335 | | * Requirements:
336 | | *
337 | | * - input must fit into 104 bits
338 | | *
339 | | * _Available since v4.7._
340 | | */
341 | | function toUint104(uint256 value) internal pure returns (uint104) {
342 | | require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
343 | | return uint104(value);
344 | | }
345 | |
346 | | /**
347 | | * @dev Returns the downcasted uint96 from uint256, reverting on
348 | | * overflow (when the input is greater than largest uint96).
349 | | *
350 | | * Counterpart to Solidity's `uint96` operator.
351 | | *
352 | | * Requirements:
353 | | *
354 | | * - input must fit into 96 bits
355 | | *
356 | | * _Available since v4.2._
357 | | */
358 | | function toUint96(uint256 value) internal pure returns (uint96) {
359 | | require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
360 | | return uint96(value);
361 | | }
362 | |
363 | | /**
364 | | * @dev Returns the downcasted uint88 from uint256, reverting on
365 | | * overflow (when the input is greater than largest uint88).
366 | | *
367 | | * Counterpart to Solidity's `uint88` operator.
368 | | *
369 | | * Requirements:
370 | | *
371 | | * - input must fit into 88 bits
372 | | *
373 | | * _Available since v4.7._
374 | | */
375 | | function toUint88(uint256 value) internal pure returns (uint88) {
376 | | require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
377 | | return uint88(value);
378 | | }
379 | |
380 | | /**
381 | | * @dev Returns the downcasted uint80 from uint256, reverting on
382 | | * overflow (when the input is greater than largest uint80).
383 | | *
384 | | * Counterpart to Solidity's `uint80` operator.
385 | | *
386 | | * Requirements:
387 | | *
388 | | * - input must fit into 80 bits
389 | | *
390 | | * _Available since v4.7._
391 | | */
392 | | function toUint80(uint256 value) internal pure returns (uint80) {
393 | | require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
394 | | return uint80(value);
395 | | }
396 | |
397 | | /**
398 | | * @dev Returns the downcasted uint72 from uint256, reverting on
399 | | * overflow (when the input is greater than largest uint72).
400 | | *
401 | | * Counterpart to Solidity's `uint72` operator.
402 | | *
403 | | * Requirements:
404 | | *
405 | | * - input must fit into 72 bits
406 | | *
407 | | * _Available since v4.7._
408 | | */
409 | | function toUint72(uint256 value) internal pure returns (uint72) {
410 | | require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
411 | | return uint72(value);
412 | | }
413 | |
414 | | /**
415 | | * @dev Returns the downcasted uint64 from uint256, reverting on
416 | | * overflow (when the input is greater than largest uint64).
417 | | *
418 | | * Counterpart to Solidity's `uint64` operator.
419 | | *
420 | | * Requirements:
421 | | *
422 | | * - input must fit into 64 bits
423 | | *
424 | | * _Available since v2.5._
425 | | */
426 | | function toUint64(uint256 value) internal pure returns (uint64) {
427 | | require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
428 | | return uint64(value);
429 | | }
430 | |
431 | | /**
432 | | * @dev Returns the downcasted uint56 from uint256, reverting on
433 | | * overflow (when the input is greater than largest uint56).
434 | | *
435 | | * Counterpart to Solidity's `uint56` operator.
436 | | *
437 | | * Requirements:
438 | | *
439 | | * - input must fit into 56 bits
440 | | *
441 | | * _Available since v4.7._
442 | | */
443 | | function toUint56(uint256 value) internal pure returns (uint56) {
444 | | require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
445 | | return uint56(value);
446 | | }
447 | |
448 | | /**
449 | | * @dev Returns the downcasted uint48 from uint256, reverting on
450 | | * overflow (when the input is greater than largest uint48).
451 | | *
452 | | * Counterpart to Solidity's `uint48` operator.
453 | | *
454 | | * Requirements:
455 | | *
456 | | * - input must fit into 48 bits
457 | | *
458 | | * _Available since v4.7._
459 | | */
460 | | function toUint48(uint256 value) internal pure returns (uint48) {
461 | | require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
462 | | return uint48(value);
463 | | }
464 | |
465 | | /**
466 | | * @dev Returns the downcasted uint40 from uint256, reverting on
467 | | * overflow (when the input is greater than largest uint40).
468 | | *
469 | | * Counterpart to Solidity's `uint40` operator.
470 | | *
471 | | * Requirements:
472 | | *
473 | | * - input must fit into 40 bits
474 | | *
475 | | * _Available since v4.7._
476 | | */
477 | | function toUint40(uint256 value) internal pure returns (uint40) {
478 | | require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
479 | | return uint40(value);
480 | | }
481 | |
482 | | /**
483 | | * @dev Returns the downcasted uint32 from uint256, reverting on
484 | | * overflow (when the input is greater than largest uint32).
485 | | *
486 | | * Counterpart to Solidity's `uint32` operator.
487 | | *
488 | | * Requirements:
489 | | *
490 | | * - input must fit into 32 bits
491 | | *
492 | | * _Available since v2.5._
493 | | */
494 | | function toUint32(uint256 value) internal pure returns (uint32) {
495 | | require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
496 | | return uint32(value);
497 | | }
498 | |
499 | | /**
500 | | * @dev Returns the downcasted uint24 from uint256, reverting on
501 | | * overflow (when the input is greater than largest uint24).
502 | | *
503 | | * Counterpart to Solidity's `uint24` operator.
504 | | *
505 | | * Requirements:
506 | | *
507 | | * - input must fit into 24 bits
508 | | *
509 | | * _Available since v4.7._
510 | | */
511 | | function toUint24(uint256 value) internal pure returns (uint24) {
512 | | require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
513 | | return uint24(value);
514 | | }
515 | |
516 | | /**
517 | | * @dev Returns the downcasted uint16 from uint256, reverting on
518 | | * overflow (when the input is greater than largest uint16).
519 | | *
520 | | * Counterpart to Solidity's `uint16` operator.
521 | | *
522 | | * Requirements:
523 | | *
524 | | * - input must fit into 16 bits
525 | | *
526 | | * _Available since v2.5._
527 | | */
528 | | function toUint16(uint256 value) internal pure returns (uint16) {
529 | | require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
530 | | return uint16(value);
531 | | }
532 | |
533 | | /**
534 | | * @dev Returns the downcasted uint8 from uint256, reverting on
535 | | * overflow (when the input is greater than largest uint8).
536 | | *
537 | | * Counterpart to Solidity's `uint8` operator.
538 | | *
539 | | * Requirements:
540 | | *
541 | | * - input must fit into 8 bits
542 | | *
543 | | * _Available since v2.5._
544 | | */
545 | | function toUint8(uint256 value) internal pure returns (uint8) {
546 | | require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
547 | | return uint8(value);
548 | | }
549 | |
550 | | /**
551 | | * @dev Converts a signed int256 into an unsigned uint256.
552 | | *
553 | | * Requirements:
554 | | *
555 | | * - input must be greater than or equal to 0.
556 | | *
557 | | * _Available since v3.0._
558 | | */
559 | * | function toUint256(int256 value) internal pure returns (uint256) {
560 | * | require(value >= 0, "SafeCast: value must be positive");
561 | * | return uint256(value);
562 | | }
563 | |
564 | | /**
565 | | * @dev Returns the downcasted int248 from int256, reverting on
566 | | * overflow (when the input is less than smallest int248 or
567 | | * greater than largest int248).
568 | | *
569 | | * Counterpart to Solidity's `int248` operator.
570 | | *
571 | | * Requirements:
572 | | *
573 | | * - input must fit into 248 bits
574 | | *
575 | | * _Available since v4.7._
576 | | */
577 | | function toInt248(int256 value) internal pure returns (int248 downcasted) {
578 | | downcasted = int248(value);
579 | | require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
580 | | }
581 | |
582 | | /**
583 | | * @dev Returns the downcasted int240 from int256, reverting on
584 | | * overflow (when the input is less than smallest int240 or
585 | | * greater than largest int240).
586 | | *
587 | | * Counterpart to Solidity's `int240` operator.
588 | | *
589 | | * Requirements:
590 | | *
591 | | * - input must fit into 240 bits
592 | | *
593 | | * _Available since v4.7._
594 | | */
595 | | function toInt240(int256 value) internal pure returns (int240 downcasted) {
596 | | downcasted = int240(value);
597 | | require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
598 | | }
599 | |
600 | | /**
601 | | * @dev Returns the downcasted int232 from int256, reverting on
602 | | * overflow (when the input is less than smallest int232 or
603 | | * greater than largest int232).
604 | | *
605 | | * Counterpart to Solidity's `int232` operator.
606 | | *
607 | | * Requirements:
608 | | *
609 | | * - input must fit into 232 bits
610 | | *
611 | | * _Available since v4.7._
612 | | */
613 | | function toInt232(int256 value) internal pure returns (int232 downcasted) {
614 | | downcasted = int232(value);
615 | | require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
616 | | }
617 | |
618 | | /**
619 | | * @dev Returns the downcasted int224 from int256, reverting on
620 | | * overflow (when the input is less than smallest int224 or
621 | | * greater than largest int224).
622 | | *
623 | | * Counterpart to Solidity's `int224` operator.
624 | | *
625 | | * Requirements:
626 | | *
627 | | * - input must fit into 224 bits
628 | | *
629 | | * _Available since v4.7._
630 | | */
631 | | function toInt224(int256 value) internal pure returns (int224 downcasted) {
632 | | downcasted = int224(value);
633 | | require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
634 | | }
635 | |
636 | | /**
637 | | * @dev Returns the downcasted int216 from int256, reverting on
638 | | * overflow (when the input is less than smallest int216 or
639 | | * greater than largest int216).
640 | | *
641 | | * Counterpart to Solidity's `int216` operator.
642 | | *
643 | | * Requirements:
644 | | *
645 | | * - input must fit into 216 bits
646 | | *
647 | | * _Available since v4.7._
648 | | */
649 | | function toInt216(int256 value) internal pure returns (int216 downcasted) {
650 | | downcasted = int216(value);
651 | | require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
652 | | }
653 | |
654 | | /**
655 | | * @dev Returns the downcasted int208 from int256, reverting on
656 | | * overflow (when the input is less than smallest int208 or
657 | | * greater than largest int208).
658 | | *
659 | | * Counterpart to Solidity's `int208` operator.
660 | | *
661 | | * Requirements:
662 | | *
663 | | * - input must fit into 208 bits
664 | | *
665 | | * _Available since v4.7._
666 | | */
667 | | function toInt208(int256 value) internal pure returns (int208 downcasted) {
668 | | downcasted = int208(value);
669 | | require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
670 | | }
671 | |
672 | | /**
673 | | * @dev Returns the downcasted int200 from int256, reverting on
674 | | * overflow (when the input is less than smallest int200 or
675 | | * greater than largest int200).
676 | | *
677 | | * Counterpart to Solidity's `int200` operator.
678 | | *
679 | | * Requirements:
680 | | *
681 | | * - input must fit into 200 bits
682 | | *
683 | | * _Available since v4.7._
684 | | */
685 | | function toInt200(int256 value) internal pure returns (int200 downcasted) {
686 | | downcasted = int200(value);
687 | | require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
688 | | }
689 | |
690 | | /**
691 | | * @dev Returns the downcasted int192 from int256, reverting on
692 | | * overflow (when the input is less than smallest int192 or
693 | | * greater than largest int192).
694 | | *
695 | | * Counterpart to Solidity's `int192` operator.
696 | | *
697 | | * Requirements:
698 | | *
699 | | * - input must fit into 192 bits
700 | | *
701 | | * _Available since v4.7._
702 | | */
703 | | function toInt192(int256 value) internal pure returns (int192 downcasted) {
704 | | downcasted = int192(value);
705 | | require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
706 | | }
707 | |
708 | | /**
709 | | * @dev Returns the downcasted int184 from int256, reverting on
710 | | * overflow (when the input is less than smallest int184 or
711 | | * greater than largest int184).
712 | | *
713 | | * Counterpart to Solidity's `int184` operator.
714 | | *
715 | | * Requirements:
716 | | *
717 | | * - input must fit into 184 bits
718 | | *
719 | | * _Available since v4.7._
720 | | */
721 | | function toInt184(int256 value) internal pure returns (int184 downcasted) {
722 | | downcasted = int184(value);
723 | | require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
724 | | }
725 | |
726 | | /**
727 | | * @dev Returns the downcasted int176 from int256, reverting on
728 | | * overflow (when the input is less than smallest int176 or
729 | | * greater than largest int176).
730 | | *
731 | | * Counterpart to Solidity's `int176` operator.
732 | | *
733 | | * Requirements:
734 | | *
735 | | * - input must fit into 176 bits
736 | | *
737 | | * _Available since v4.7._
738 | | */
739 | | function toInt176(int256 value) internal pure returns (int176 downcasted) {
740 | | downcasted = int176(value);
741 | | require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
742 | | }
743 | |
744 | | /**
745 | | * @dev Returns the downcasted int168 from int256, reverting on
746 | | * overflow (when the input is less than smallest int168 or
747 | | * greater than largest int168).
748 | | *
749 | | * Counterpart to Solidity's `int168` operator.
750 | | *
751 | | * Requirements:
752 | | *
753 | | * - input must fit into 168 bits
754 | | *
755 | | * _Available since v4.7._
756 | | */
757 | | function toInt168(int256 value) internal pure returns (int168 downcasted) {
758 | | downcasted = int168(value);
759 | | require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
760 | | }
761 | |
762 | | /**
763 | | * @dev Returns the downcasted int160 from int256, reverting on
764 | | * overflow (when the input is less than smallest int160 or
765 | | * greater than largest int160).
766 | | *
767 | | * Counterpart to Solidity's `int160` operator.
768 | | *
769 | | * Requirements:
770 | | *
771 | | * - input must fit into 160 bits
772 | | *
773 | | * _Available since v4.7._
774 | | */
775 | | function toInt160(int256 value) internal pure returns (int160 downcasted) {
776 | | downcasted = int160(value);
777 | | require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
778 | | }
779 | |
780 | | /**
781 | | * @dev Returns the downcasted int152 from int256, reverting on
782 | | * overflow (when the input is less than smallest int152 or
783 | | * greater than largest int152).
784 | | *
785 | | * Counterpart to Solidity's `int152` operator.
786 | | *
787 | | * Requirements:
788 | | *
789 | | * - input must fit into 152 bits
790 | | *
791 | | * _Available since v4.7._
792 | | */
793 | | function toInt152(int256 value) internal pure returns (int152 downcasted) {
794 | | downcasted = int152(value);
795 | | require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
796 | | }
797 | |
798 | | /**
799 | | * @dev Returns the downcasted int144 from int256, reverting on
800 | | * overflow (when the input is less than smallest int144 or
801 | | * greater than largest int144).
802 | | *
803 | | * Counterpart to Solidity's `int144` operator.
804 | | *
805 | | * Requirements:
806 | | *
807 | | * - input must fit into 144 bits
808 | | *
809 | | * _Available since v4.7._
810 | | */
811 | | function toInt144(int256 value) internal pure returns (int144 downcasted) {
812 | | downcasted = int144(value);
813 | | require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
814 | | }
815 | |
816 | | /**
817 | | * @dev Returns the downcasted int136 from int256, reverting on
818 | | * overflow (when the input is less than smallest int136 or
819 | | * greater than largest int136).
820 | | *
821 | | * Counterpart to Solidity's `int136` operator.
822 | | *
823 | | * Requirements:
824 | | *
825 | | * - input must fit into 136 bits
826 | | *
827 | | * _Available since v4.7._
828 | | */
829 | | function toInt136(int256 value) internal pure returns (int136 downcasted) {
830 | | downcasted = int136(value);
831 | | require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
832 | | }
833 | |
834 | | /**
835 | | * @dev Returns the downcasted int128 from int256, reverting on
836 | | * overflow (when the input is less than smallest int128 or
837 | | * greater than largest int128).
838 | | *
839 | | * Counterpart to Solidity's `int128` operator.
840 | | *
841 | | * Requirements:
842 | | *
843 | | * - input must fit into 128 bits
844 | | *
845 | | * _Available since v3.1._
846 | | */
847 | | function toInt128(int256 value) internal pure returns (int128 downcasted) {
848 | | downcasted = int128(value);
849 | | require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
850 | | }
851 | |
852 | | /**
853 | | * @dev Returns the downcasted int120 from int256, reverting on
854 | | * overflow (when the input is less than smallest int120 or
855 | | * greater than largest int120).
856 | | *
857 | | * Counterpart to Solidity's `int120` operator.
858 | | *
859 | | * Requirements:
860 | | *
861 | | * - input must fit into 120 bits
862 | | *
863 | | * _Available since v4.7._
864 | | */
865 | | function toInt120(int256 value) internal pure returns (int120 downcasted) {
866 | | downcasted = int120(value);
867 | | require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
868 | | }
869 | |
870 | | /**
871 | | * @dev Returns the downcasted int112 from int256, reverting on
872 | | * overflow (when the input is less than smallest int112 or
873 | | * greater than largest int112).
874 | | *
875 | | * Counterpart to Solidity's `int112` operator.
876 | | *
877 | | * Requirements:
878 | | *
879 | | * - input must fit into 112 bits
880 | | *
881 | | * _Available since v4.7._
882 | | */
883 | | function toInt112(int256 value) internal pure returns (int112 downcasted) {
884 | | downcasted = int112(value);
885 | | require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
886 | | }
887 | |
888 | | /**
889 | | * @dev Returns the downcasted int104 from int256, reverting on
890 | | * overflow (when the input is less than smallest int104 or
891 | | * greater than largest int104).
892 | | *
893 | | * Counterpart to Solidity's `int104` operator.
894 | | *
895 | | * Requirements:
896 | | *
897 | | * - input must fit into 104 bits
898 | | *
899 | | * _Available since v4.7._
900 | | */
901 | | function toInt104(int256 value) internal pure returns (int104 downcasted) {
902 | | downcasted = int104(value);
903 | | require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
904 | | }
905 | |
906 | | /**
907 | | * @dev Returns the downcasted int96 from int256, reverting on
908 | | * overflow (when the input is less than smallest int96 or
909 | | * greater than largest int96).
910 | | *
911 | | * Counterpart to Solidity's `int96` operator.
912 | | *
913 | | * Requirements:
914 | | *
915 | | * - input must fit into 96 bits
916 | | *
917 | | * _Available since v4.7._
918 | | */
919 | | function toInt96(int256 value) internal pure returns (int96 downcasted) {
920 | | downcasted = int96(value);
921 | | require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
922 | | }
923 | |
924 | | /**
925 | | * @dev Returns the downcasted int88 from int256, reverting on
926 | | * overflow (when the input is less than smallest int88 or
927 | | * greater than largest int88).
928 | | *
929 | | * Counterpart to Solidity's `int88` operator.
930 | | *
931 | | * Requirements:
932 | | *
933 | | * - input must fit into 88 bits
934 | | *
935 | | * _Available since v4.7._
936 | | */
937 | | function toInt88(int256 value) internal pure returns (int88 downcasted) {
938 | | downcasted = int88(value);
939 | | require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
940 | | }
941 | |
942 | | /**
943 | | * @dev Returns the downcasted int80 from int256, reverting on
944 | | * overflow (when the input is less than smallest int80 or
945 | | * greater than largest int80).
946 | | *
947 | | * Counterpart to Solidity's `int80` operator.
948 | | *
949 | | * Requirements:
950 | | *
951 | | * - input must fit into 80 bits
952 | | *
953 | | * _Available since v4.7._
954 | | */
955 | | function toInt80(int256 value) internal pure returns (int80 downcasted) {
956 | | downcasted = int80(value);
957 | | require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
958 | | }
959 | |
960 | | /**
961 | | * @dev Returns the downcasted int72 from int256, reverting on
962 | | * overflow (when the input is less than smallest int72 or
963 | | * greater than largest int72).
964 | | *
965 | | * Counterpart to Solidity's `int72` operator.
966 | | *
967 | | * Requirements:
968 | | *
969 | | * - input must fit into 72 bits
970 | | *
971 | | * _Available since v4.7._
972 | | */
973 | | function toInt72(int256 value) internal pure returns (int72 downcasted) {
974 | | downcasted = int72(value);
975 | | require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
976 | | }
977 | |
978 | | /**
979 | | * @dev Returns the downcasted int64 from int256, reverting on
980 | | * overflow (when the input is less than smallest int64 or
981 | | * greater than largest int64).
982 | | *
983 | | * Counterpart to Solidity's `int64` operator.
984 | | *
985 | | * Requirements:
986 | | *
987 | | * - input must fit into 64 bits
988 | | *
989 | | * _Available since v3.1._
990 | | */
991 | | function toInt64(int256 value) internal pure returns (int64 downcasted) {
992 | | downcasted = int64(value);
993 | | require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
994 | | }
995 | |
996 | | /**
997 | | * @dev Returns the downcasted int56 from int256, reverting on
998 | | * overflow (when the input is less than smallest int56 or
999 | | * greater than largest int56).
1000 | | *
1001 | | * Counterpart to Solidity's `int56` operator.
1002 | | *
1003 | | * Requirements:
1004 | | *
1005 | | * - input must fit into 56 bits
1006 | | *
1007 | | * _Available since v4.7._
1008 | | */
1009 | | function toInt56(int256 value) internal pure returns (int56 downcasted) {
1010 | | downcasted = int56(value);
1011 | | require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
1012 | | }
1013 | |
1014 | | /**
1015 | | * @dev Returns the downcasted int48 from int256, reverting on
1016 | | * overflow (when the input is less than smallest int48 or
1017 | | * greater than largest int48).
1018 | | *
1019 | | * Counterpart to Solidity's `int48` operator.
1020 | | *
1021 | | * Requirements:
1022 | | *
1023 | | * - input must fit into 48 bits
1024 | | *
1025 | | * _Available since v4.7._
1026 | | */
1027 | | function toInt48(int256 value) internal pure returns (int48 downcasted) {
1028 | | downcasted = int48(value);
1029 | | require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
1030 | | }
1031 | |
1032 | | /**
1033 | | * @dev Returns the downcasted int40 from int256, reverting on
1034 | | * overflow (when the input is less than smallest int40 or
1035 | | * greater than largest int40).
1036 | | *
1037 | | * Counterpart to Solidity's `int40` operator.
1038 | | *
1039 | | * Requirements:
1040 | | *
1041 | | * - input must fit into 40 bits
1042 | | *
1043 | | * _Available since v4.7._
1044 | | */
1045 | | function toInt40(int256 value) internal pure returns (int40 downcasted) {
1046 | | downcasted = int40(value);
1047 | | require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
1048 | | }
1049 | |
1050 | | /**
1051 | | * @dev Returns the downcasted int32 from int256, reverting on
1052 | | * overflow (when the input is less than smallest int32 or
1053 | | * greater than largest int32).
1054 | | *
1055 | | * Counterpart to Solidity's `int32` operator.
1056 | | *
1057 | | * Requirements:
1058 | | *
1059 | | * - input must fit into 32 bits
1060 | | *
1061 | | * _Available since v3.1._
1062 | | */
1063 | | function toInt32(int256 value) internal pure returns (int32 downcasted) {
1064 | | downcasted = int32(value);
1065 | | require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
1066 | | }
1067 | |
1068 | | /**
1069 | | * @dev Returns the downcasted int24 from int256, reverting on
1070 | | * overflow (when the input is less than smallest int24 or
1071 | | * greater than largest int24).
1072 | | *
1073 | | * Counterpart to Solidity's `int24` operator.
1074 | | *
1075 | | * Requirements:
1076 | | *
1077 | | * - input must fit into 24 bits
1078 | | *
1079 | | * _Available since v4.7._
1080 | | */
1081 | | function toInt24(int256 value) internal pure returns (int24 downcasted) {
1082 | | downcasted = int24(value);
1083 | | require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
1084 | | }
1085 | |
1086 | | /**
1087 | | * @dev Returns the downcasted int16 from int256, reverting on
1088 | | * overflow (when the input is less than smallest int16 or
1089 | | * greater than largest int16).
1090 | | *
1091 | | * Counterpart to Solidity's `int16` operator.
1092 | | *
1093 | | * Requirements:
1094 | | *
1095 | | * - input must fit into 16 bits
1096 | | *
1097 | | * _Available since v3.1._
1098 | | */
1099 | | function toInt16(int256 value) internal pure returns (int16 downcasted) {
1100 | | downcasted = int16(value);
1101 | | require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
1102 | | }
1103 | |
1104 | | /**
1105 | | * @dev Returns the downcasted int8 from int256, reverting on
1106 | | * overflow (when the input is less than smallest int8 or
1107 | | * greater than largest int8).
1108 | | *
1109 | | * Counterpart to Solidity's `int8` operator.
1110 | | *
1111 | | * Requirements:
1112 | | *
1113 | | * - input must fit into 8 bits
1114 | | *
1115 | | * _Available since v3.1._
1116 | | */
1117 | | function toInt8(int256 value) internal pure returns (int8 downcasted) {
1118 | | downcasted = int8(value);
1119 | | require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
1120 | | }
1121 | |
1122 | | /**
1123 | | * @dev Converts an unsigned uint256 into a signed int256.
1124 | | *
1125 | | * Requirements:
1126 | | *
1127 | | * - input must be less than or equal to maxInt256.
1128 | | *
1129 | | * _Available since v3.0._
1130 | | */
1131 | * | function toInt256(uint256 value) internal pure returns (int256) {
1132 | | // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
1133 | * | require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
1134 | * | return int256(value);
1135 | | }
1136 | | }
1137 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | // CAUTION
7 | | // This version of SafeMath should only be used with Solidity 0.8 or later,
8 | | // because it relies on the compiler's built in overflow checks.
9 | |
10 | | /**
11 | | * @dev Wrappers over Solidity's arithmetic operations.
12 | | *
13 | | * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
14 | | * now has built in overflow checking.
15 | | */
16 | * | library SafeMath {
17 | | /**
18 | | * @dev Returns the addition of two unsigned integers, with an overflow flag.
19 | | *
20 | | * _Available since v3.4._
21 | | */
22 | | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
23 | | unchecked {
24 | | uint256 c = a + b;
25 | | if (c < a) return (false, 0);
26 | | return (true, c);
27 | | }
28 | | }
29 | |
30 | | /**
31 | | * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
32 | | *
33 | | * _Available since v3.4._
34 | | */
35 | | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
36 | | unchecked {
37 | | if (b > a) return (false, 0);
38 | | return (true, a - b);
39 | | }
40 | | }
41 | |
42 | | /**
43 | | * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
44 | | *
45 | | * _Available since v3.4._
46 | | */
47 | | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
48 | | unchecked {
49 | | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
50 | | // benefit is lost if 'b' is also tested.
51 | | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
52 | | if (a == 0) return (true, 0);
53 | | uint256 c = a * b;
54 | | if (c / a != b) return (false, 0);
55 | | return (true, c);
56 | | }
57 | | }
58 | |
59 | | /**
60 | | * @dev Returns the division of two unsigned integers, with a division by zero flag.
61 | | *
62 | | * _Available since v3.4._
63 | | */
64 | | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
65 | | unchecked {
66 | | if (b == 0) return (false, 0);
67 | | return (true, a / b);
68 | | }
69 | | }
70 | |
71 | | /**
72 | | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
73 | | *
74 | | * _Available since v3.4._
75 | | */
76 | | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
77 | | unchecked {
78 | | if (b == 0) return (false, 0);
79 | | return (true, a % b);
80 | | }
81 | | }
82 | |
83 | | /**
84 | | * @dev Returns the addition of two unsigned integers, reverting on
85 | | * overflow.
86 | | *
87 | | * Counterpart to Solidity's `+` operator.
88 | | *
89 | | * Requirements:
90 | | *
91 | | * - Addition cannot overflow.
92 | | */
93 | | function add(uint256 a, uint256 b) internal pure returns (uint256) {
94 | | return a + b;
95 | | }
96 | |
97 | | /**
98 | | * @dev Returns the subtraction of two unsigned integers, reverting on
99 | | * overflow (when the result is negative).
100 | | *
101 | | * Counterpart to Solidity's `-` operator.
102 | | *
103 | | * Requirements:
104 | | *
105 | | * - Subtraction cannot overflow.
106 | | */
107 | | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
108 | | return a - b;
109 | | }
110 | |
111 | | /**
112 | | * @dev Returns the multiplication of two unsigned integers, reverting on
113 | | * overflow.
114 | | *
115 | | * Counterpart to Solidity's `*` operator.
116 | | *
117 | | * Requirements:
118 | | *
119 | | * - Multiplication cannot overflow.
120 | | */
121 | | function mul(uint256 a, uint256 b) internal pure returns (uint256) {
122 | | return a * b;
123 | | }
124 | |
125 | | /**
126 | | * @dev Returns the integer division of two unsigned integers, reverting on
127 | | * division by zero. The result is rounded towards zero.
128 | | *
129 | | * Counterpart to Solidity's `/` operator.
130 | | *
131 | | * Requirements:
132 | | *
133 | | * - The divisor cannot be zero.
134 | | */
135 | | function div(uint256 a, uint256 b) internal pure returns (uint256) {
136 | | return a / b;
137 | | }
138 | |
139 | | /**
140 | | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
141 | | * reverting when dividing by zero.
142 | | *
143 | | * Counterpart to Solidity's `%` operator. This function uses a `revert`
144 | | * opcode (which leaves remaining gas untouched) while Solidity uses an
145 | | * invalid opcode to revert (consuming all remaining gas).
146 | | *
147 | | * Requirements:
148 | | *
149 | | * - The divisor cannot be zero.
150 | | */
151 | | function mod(uint256 a, uint256 b) internal pure returns (uint256) {
152 | | return a % b;
153 | | }
154 | |
155 | | /**
156 | | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
157 | | * overflow (when the result is negative).
158 | | *
159 | | * CAUTION: This function is deprecated because it requires allocating memory for the error
160 | | * message unnecessarily. For custom revert reasons use {trySub}.
161 | | *
162 | | * Counterpart to Solidity's `-` operator.
163 | | *
164 | | * Requirements:
165 | | *
166 | | * - Subtraction cannot overflow.
167 | | */
168 | | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
169 | | unchecked {
170 | | require(b <= a, errorMessage);
171 | | return a - b;
172 | | }
173 | | }
174 | |
175 | | /**
176 | | * @dev Returns the integer division of two unsigned integers, reverting with custom message on
177 | | * division by zero. The result is rounded towards zero.
178 | | *
179 | | * Counterpart to Solidity's `/` operator. Note: this function uses a
180 | | * `revert` opcode (which leaves remaining gas untouched) while Solidity
181 | | * uses an invalid opcode to revert (consuming all remaining gas).
182 | | *
183 | | * Requirements:
184 | | *
185 | | * - The divisor cannot be zero.
186 | | */
187 | | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
188 | | unchecked {
189 | | require(b > 0, errorMessage);
190 | | return a / b;
191 | | }
192 | | }
193 | |
194 | | /**
195 | | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
196 | | * reverting with custom message when dividing by zero.
197 | | *
198 | | * CAUTION: This function is deprecated because it requires allocating memory for the error
199 | | * message unnecessarily. For custom revert reasons use {tryMod}.
200 | | *
201 | | * Counterpart to Solidity's `%` operator. This function uses a `revert`
202 | | * opcode (which leaves remaining gas untouched) while Solidity uses an
203 | | * invalid opcode to revert (consuming all remaining gas).
204 | | *
205 | | * Requirements:
206 | | *
207 | | * - The divisor cannot be zero.
208 | | */
209 | | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
210 | | unchecked {
211 | | require(b > 0, errorMessage);
212 | | return a % b;
213 | | }
214 | | }
215 | | }
216 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Standard signed math utilities missing in the Solidity language.
8 | | */
9 | * | library SignedMath {
10 | | /**
11 | | * @dev Returns the largest of two signed numbers.
12 | | */
13 | | function max(int256 a, int256 b) internal pure returns (int256) {
14 | | return a > b ? a : b;
15 | | }
16 | |
17 | | /**
18 | | * @dev Returns the smallest of two signed numbers.
19 | | */
20 | | function min(int256 a, int256 b) internal pure returns (int256) {
21 | | return a < b ? a : b;
22 | | }
23 | |
24 | | /**
25 | | * @dev Returns the average of two signed numbers without overflow.
26 | | * The result is rounded towards zero.
27 | | */
28 | | function average(int256 a, int256 b) internal pure returns (int256) {
29 | | // Formula from the book "Hacker's Delight"
30 | | int256 x = (a & b) + ((a ^ b) >> 1);
31 | | return x + (int256(uint256(x) >> 255) & (a ^ b));
32 | | }
33 | |
34 | | /**
35 | | * @dev Returns the absolute unsigned value of a signed value.
36 | | */
37 | * | function abs(int256 n) internal pure returns (uint256) {
38 | | unchecked {
39 | | // must be unchecked in order to support `n = type(int256).min`
40 | * | return uint256(n >= 0 ? n : -n);
41 | | }
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SignedSafeMath.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol)
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @dev Wrappers over Solidity's arithmetic operations.
8 | | *
9 | | * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
10 | | * now has built in overflow checking.
11 | | */
12 | * | library SignedSafeMath {
13 | | /**
14 | | * @dev Returns the multiplication of two signed integers, reverting on
15 | | * overflow.
16 | | *
17 | | * Counterpart to Solidity's `*` operator.
18 | | *
19 | | * Requirements:
20 | | *
21 | | * - Multiplication cannot overflow.
22 | | */
23 | | function mul(int256 a, int256 b) internal pure returns (int256) {
24 | | return a * b;
25 | | }
26 | |
27 | | /**
28 | | * @dev Returns the integer division of two signed integers. Reverts on
29 | | * division by zero. The result is rounded towards zero.
30 | | *
31 | | * Counterpart to Solidity's `/` operator.
32 | | *
33 | | * Requirements:
34 | | *
35 | | * - The divisor cannot be zero.
36 | | */
37 | | function div(int256 a, int256 b) internal pure returns (int256) {
38 | | return a / b;
39 | | }
40 | |
41 | | /**
42 | | * @dev Returns the subtraction of two signed integers, reverting on
43 | | * overflow.
44 | | *
45 | | * Counterpart to Solidity's `-` operator.
46 | | *
47 | | * Requirements:
48 | | *
49 | | * - Subtraction cannot overflow.
50 | | */
51 | | function sub(int256 a, int256 b) internal pure returns (int256) {
52 | | return a - b;
53 | | }
54 | |
55 | | /**
56 | | * @dev Returns the addition of two signed integers, reverting on
57 | | * overflow.
58 | | *
59 | | * Counterpart to Solidity's `+` operator.
60 | | *
61 | | * Requirements:
62 | | *
63 | | * - Addition cannot overflow.
64 | | */
65 | | function add(int256 a, int256 b) internal pure returns (int256) {
66 | | return a + b;
67 | | }
68 | | }
69 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/structs/DoubleEndedQueue.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/DoubleEndedQueue.sol)
3 | | pragma solidity ^0.8.4;
4 | |
5 | | import "../math/SafeCast.sol";
6 | |
7 | | /**
8 | | * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
9 | | * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
10 | | * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
11 | | * the existing queue contents are left in storage.
12 | | *
13 | | * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
14 | | * used in storage, and not in memory.
15 | | * ```solidity
16 | | * DoubleEndedQueue.Bytes32Deque queue;
17 | | * ```
18 | | *
19 | | * _Available since v4.6._
20 | | */
21 | * | library DoubleEndedQueue {
22 | | /**
23 | | * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
24 | | */
25 | | error Empty();
26 | |
27 | | /**
28 | | * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
29 | | */
30 | | error OutOfBounds();
31 | |
32 | | /**
33 | | * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
34 | | * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
35 | | * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
36 | | *
37 | | * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
38 | | * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
39 | | * lead to unexpected behavior.
40 | | *
41 | | * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
42 | | * data[end - 1].
43 | | */
44 | | struct Bytes32Deque {
45 | | int128 _begin;
46 | | int128 _end;
47 | | mapping(int128 => bytes32) _data;
48 | | }
49 | |
50 | | /**
51 | | * @dev Inserts an item at the end of the queue.
52 | | */
53 | | function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
54 | | int128 backIndex = deque._end;
55 | | deque._data[backIndex] = value;
56 | | unchecked {
57 | | deque._end = backIndex + 1;
58 | | }
59 | | }
60 | |
61 | | /**
62 | | * @dev Removes the item at the end of the queue and returns it.
63 | | *
64 | | * Reverts with `Empty` if the queue is empty.
65 | | */
66 | | function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
67 | | if (empty(deque)) revert Empty();
68 | | int128 backIndex;
69 | | unchecked {
70 | | backIndex = deque._end - 1;
71 | | }
72 | | value = deque._data[backIndex];
73 | | delete deque._data[backIndex];
74 | | deque._end = backIndex;
75 | | }
76 | |
77 | | /**
78 | | * @dev Inserts an item at the beginning of the queue.
79 | | */
80 | | function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
81 | | int128 frontIndex;
82 | | unchecked {
83 | | frontIndex = deque._begin - 1;
84 | | }
85 | | deque._data[frontIndex] = value;
86 | | deque._begin = frontIndex;
87 | | }
88 | |
89 | | /**
90 | | * @dev Removes the item at the beginning of the queue and returns it.
91 | | *
92 | | * Reverts with `Empty` if the queue is empty.
93 | | */
94 | | function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
95 | | if (empty(deque)) revert Empty();
96 | | int128 frontIndex = deque._begin;
97 | | value = deque._data[frontIndex];
98 | | delete deque._data[frontIndex];
99 | | unchecked {
100 | | deque._begin = frontIndex + 1;
101 | | }
102 | | }
103 | |
104 | | /**
105 | | * @dev Returns the item at the beginning of the queue.
106 | | *
107 | | * Reverts with `Empty` if the queue is empty.
108 | | */
109 | | function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
110 | | if (empty(deque)) revert Empty();
111 | | int128 frontIndex = deque._begin;
112 | | return deque._data[frontIndex];
113 | | }
114 | |
115 | | /**
116 | | * @dev Returns the item at the end of the queue.
117 | | *
118 | | * Reverts with `Empty` if the queue is empty.
119 | | */
120 | | function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
121 | | if (empty(deque)) revert Empty();
122 | | int128 backIndex;
123 | | unchecked {
124 | | backIndex = deque._end - 1;
125 | | }
126 | | return deque._data[backIndex];
127 | | }
128 | |
129 | | /**
130 | | * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
131 | | * `length(deque) - 1`.
132 | | *
133 | | * Reverts with `OutOfBounds` if the index is out of bounds.
134 | | */
135 | | function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
136 | | // int256(deque._begin) is a safe upcast
137 | | int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
138 | | if (idx >= deque._end) revert OutOfBounds();
139 | | return deque._data[idx];
140 | | }
141 | |
142 | | /**
143 | | * @dev Resets the queue back to being empty.
144 | | *
145 | | * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
146 | | * out on potential gas refunds.
147 | | */
148 | | function clear(Bytes32Deque storage deque) internal {
149 | | deque._begin = 0;
150 | | deque._end = 0;
151 | | }
152 | |
153 | | /**
154 | | * @dev Returns the number of items in the queue.
155 | | */
156 | | function length(Bytes32Deque storage deque) internal view returns (uint256) {
157 | | // The interface preserves the invariant that begin <= end so we assume this will not overflow.
158 | | // We also assume there are at most int256.max items in the queue.
159 | | unchecked {
160 | | return uint256(int256(deque._end) - int256(deque._begin));
161 | | }
162 | | }
163 | |
164 | | /**
165 | | * @dev Returns true if the queue is empty.
166 | | */
167 | | function empty(Bytes32Deque storage deque) internal view returns (bool) {
168 | | return deque._end <= deque._begin;
169 | | }
170 | | }
171 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/structs/EnumerableSet.sol
1 | | // SPDX-License-Identifier: MIT
2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
3 | | // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
4 | |
5 | | pragma solidity ^0.8.0;
6 | |
7 | | /**
8 | | * @dev Library for managing
9 | | * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
10 | | * types.
11 | | *
12 | | * Sets have the following properties:
13 | | *
14 | | * - Elements are added, removed, and checked for existence in constant time
15 | | * (O(1)).
16 | | * - Elements are enumerated in O(n). No guarantees are made on the ordering.
17 | | *
18 | | * ```solidity
19 | | * contract Example {
20 | | * // Add the library methods
21 | | * using EnumerableSet for EnumerableSet.AddressSet;
22 | | *
23 | | * // Declare a set state variable
24 | | * EnumerableSet.AddressSet private mySet;
25 | | * }
26 | | * ```
27 | | *
28 | | * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
29 | | * and `uint256` (`UintSet`) are supported.
30 | | *
31 | | * [WARNING]
32 | | * ====
33 | | * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
34 | | * unusable.
35 | | * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
36 | | *
37 | | * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
38 | | * array of EnumerableSet.
39 | | * ====
40 | | */
41 | * | library EnumerableSet {
42 | | // To implement this library for multiple types with as little code
43 | | // repetition as possible, we write it in terms of a generic Set type with
44 | | // bytes32 values.
45 | | // The Set implementation uses private functions, and user-facing
46 | | // implementations (such as AddressSet) are just wrappers around the
47 | | // underlying Set.
48 | | // This means that we can only create new EnumerableSets for types that fit
49 | | // in bytes32.
50 | |
51 | | struct Set {
52 | | // Storage of set values
53 | | bytes32[] _values;
54 | | // Position of the value in the `values` array, plus 1 because index 0
55 | | // means a value is not in the set.
56 | | mapping(bytes32 => uint256) _indexes;
57 | | }
58 | |
59 | | /**
60 | | * @dev Add a value to a set. O(1).
61 | | *
62 | | * Returns true if the value was added to the set, that is if it was not
63 | | * already present.
64 | | */
65 | * | function _add(Set storage set, bytes32 value) private returns (bool) {
66 | * | if (!_contains(set, value)) {
67 | * | set._values.push(value);
68 | | // The value is stored at length-1, but we add 1 to all indexes
69 | | // and use 0 as a sentinel value
70 | * | set._indexes[value] = set._values.length;
71 | * | return true;
72 | | } else {
73 | * | return false;
74 | | }
75 | | }
76 | |
77 | | /**
78 | | * @dev Removes a value from a set. O(1).
79 | | *
80 | | * Returns true if the value was removed from the set, that is if it was
81 | | * present.
82 | | */
83 | * | function _remove(Set storage set, bytes32 value) private returns (bool) {
84 | | // We read and store the value's index to prevent multiple reads from the same storage slot
85 | * | uint256 valueIndex = set._indexes[value];
86 | |
87 | * | if (valueIndex != 0) {
88 | | // Equivalent to contains(set, value)
89 | | // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
90 | | // the array, and then remove the last element (sometimes called as 'swap and pop').
91 | | // This modifies the order of the array, as noted in {at}.
92 | |
93 | * | uint256 toDeleteIndex = valueIndex - 1;
94 | * | uint256 lastIndex = set._values.length - 1;
95 | |
96 | * | if (lastIndex != toDeleteIndex) {
97 | * | bytes32 lastValue = set._values[lastIndex];
98 | |
99 | | // Move the last value to the index where the value to delete is
100 | * | set._values[toDeleteIndex] = lastValue;
101 | | // Update the index for the moved value
102 | * | set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
103 | | }
104 | |
105 | | // Delete the slot where the moved value was stored
106 | * | set._values.pop();
107 | |
108 | | // Delete the index for the deleted slot
109 | * | delete set._indexes[value];
110 | |
111 | * | return true;
112 | | } else {
113 | | return false;
114 | | }
115 | | }
116 | |
117 | | /**
118 | | * @dev Returns true if the value is in the set. O(1).
119 | | */
120 | * | function _contains(Set storage set, bytes32 value) private view returns (bool) {
121 | * | return set._indexes[value] != 0;
122 | | }
123 | |
124 | | /**
125 | | * @dev Returns the number of values on the set. O(1).
126 | | */
127 | * | function _length(Set storage set) private view returns (uint256) {
128 | * | return set._values.length;
129 | | }
130 | |
131 | | /**
132 | | * @dev Returns the value stored at position `index` in the set. O(1).
133 | | *
134 | | * Note that there are no guarantees on the ordering of values inside the
135 | | * array, and it may change when more values are added or removed.
136 | | *
137 | | * Requirements:
138 | | *
139 | | * - `index` must be strictly less than {length}.
140 | | */
141 | * | function _at(Set storage set, uint256 index) private view returns (bytes32) {
142 | * | return set._values[index];
143 | | }
144 | |
145 | | /**
146 | | * @dev Return the entire set in an array
147 | | *
148 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
149 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
150 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function
151 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
152 | | */
153 | | function _values(Set storage set) private view returns (bytes32[] memory) {
154 | | return set._values;
155 | | }
156 | |
157 | | // Bytes32Set
158 | |
159 | | struct Bytes32Set {
160 | | Set _inner;
161 | | }
162 | |
163 | | /**
164 | | * @dev Add a value to a set. O(1).
165 | | *
166 | | * Returns true if the value was added to the set, that is if it was not
167 | | * already present.
168 | | */
169 | * | function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
170 | * | return _add(set._inner, value);
171 | | }
172 | |
173 | | /**
174 | | * @dev Removes a value from a set. O(1).
175 | | *
176 | | * Returns true if the value was removed from the set, that is if it was
177 | | * present.
178 | | */
179 | * | function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
180 | * | return _remove(set._inner, value);
181 | | }
182 | |
183 | | /**
184 | | * @dev Returns true if the value is in the set. O(1).
185 | | */
186 | * | function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
187 | * | return _contains(set._inner, value);
188 | | }
189 | |
190 | | /**
191 | | * @dev Returns the number of values in the set. O(1).
192 | | */
193 | * | function length(Bytes32Set storage set) internal view returns (uint256) {
194 | * | return _length(set._inner);
195 | | }
196 | |
197 | | /**
198 | | * @dev Returns the value stored at position `index` in the set. O(1).
199 | | *
200 | | * Note that there are no guarantees on the ordering of values inside the
201 | | * array, and it may change when more values are added or removed.
202 | | *
203 | | * Requirements:
204 | | *
205 | | * - `index` must be strictly less than {length}.
206 | | */
207 | * | function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
208 | * | return _at(set._inner, index);
209 | | }
210 | |
211 | | /**
212 | | * @dev Return the entire set in an array
213 | | *
214 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
215 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
216 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function
217 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
218 | | */
219 | | function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
220 | | bytes32[] memory store = _values(set._inner);
221 | | bytes32[] memory result;
222 | |
223 | | /// @solidity memory-safe-assembly
224 | | assembly {
225 | | result := store
226 | | }
227 | |
228 | | return result;
229 | | }
230 | |
231 | | // AddressSet
232 | |
233 | | struct AddressSet {
234 | | Set _inner;
235 | | }
236 | |
237 | | /**
238 | | * @dev Add a value to a set. O(1).
239 | | *
240 | | * Returns true if the value was added to the set, that is if it was not
241 | | * already present.
242 | | */
243 | * | function add(AddressSet storage set, address value) internal returns (bool) {
244 | * | return _add(set._inner, bytes32(uint256(uint160(value))));
245 | | }
246 | |
247 | | /**
248 | | * @dev Removes a value from a set. O(1).
249 | | *
250 | | * Returns true if the value was removed from the set, that is if it was
251 | | * present.
252 | | */
253 | * | function remove(AddressSet storage set, address value) internal returns (bool) {
254 | * | return _remove(set._inner, bytes32(uint256(uint160(value))));
255 | | }
256 | |
257 | | /**
258 | | * @dev Returns true if the value is in the set. O(1).
259 | | */
260 | * | function contains(AddressSet storage set, address value) internal view returns (bool) {
261 | * | return _contains(set._inner, bytes32(uint256(uint160(value))));
262 | | }
263 | |
264 | | /**
265 | | * @dev Returns the number of values in the set. O(1).
266 | | */
267 | * | function length(AddressSet storage set) internal view returns (uint256) {
268 | * | return _length(set._inner);
269 | | }
270 | |
271 | | /**
272 | | * @dev Returns the value stored at position `index` in the set. O(1).
273 | | *
274 | | * Note that there are no guarantees on the ordering of values inside the
275 | | * array, and it may change when more values are added or removed.
276 | | *
277 | | * Requirements:
278 | | *
279 | | * - `index` must be strictly less than {length}.
280 | | */
281 | * | function at(AddressSet storage set, uint256 index) internal view returns (address) {
282 | * | return address(uint160(uint256(_at(set._inner, index))));
283 | | }
284 | |
285 | | /**
286 | | * @dev Return the entire set in an array
287 | | *
288 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
289 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
290 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function
291 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
292 | | */
293 | | function values(AddressSet storage set) internal view returns (address[] memory) {
294 | | bytes32[] memory store = _values(set._inner);
295 | | address[] memory result;
296 | |
297 | | /// @solidity memory-safe-assembly
298 | | assembly {
299 | | result := store
300 | | }
301 | |
302 | | return result;
303 | | }
304 | |
305 | | // UintSet
306 | |
307 | | struct UintSet {
308 | | Set _inner;
309 | | }
310 | |
311 | | /**
312 | | * @dev Add a value to a set. O(1).
313 | | *
314 | | * Returns true if the value was added to the set, that is if it was not
315 | | * already present.
316 | | */
317 | * | function add(UintSet storage set, uint256 value) internal returns (bool) {
318 | * | return _add(set._inner, bytes32(value));
319 | | }
320 | |
321 | | /**
322 | | * @dev Removes a value from a set. O(1).
323 | | *
324 | | * Returns true if the value was removed from the set, that is if it was
325 | | * present.
326 | | */
327 | * | function remove(UintSet storage set, uint256 value) internal returns (bool) {
328 | * | return _remove(set._inner, bytes32(value));
329 | | }
330 | |
331 | | /**
332 | | * @dev Returns true if the value is in the set. O(1).
333 | | */
334 | * | function contains(UintSet storage set, uint256 value) internal view returns (bool) {
335 | * | return _contains(set._inner, bytes32(value));
336 | | }
337 | |
338 | | /**
339 | | * @dev Returns the number of values in the set. O(1).
340 | | */
341 | * | function length(UintSet storage set) internal view returns (uint256) {
342 | * | return _length(set._inner);
343 | | }
344 | |
345 | | /**
346 | | * @dev Returns the value stored at position `index` in the set. O(1).
347 | | *
348 | | * Note that there are no guarantees on the ordering of values inside the
349 | | * array, and it may change when more values are added or removed.
350 | | *
351 | | * Requirements:
352 | | *
353 | | * - `index` must be strictly less than {length}.
354 | | */
355 | * | function at(UintSet storage set, uint256 index) internal view returns (uint256) {
356 | * | return uint256(_at(set._inner, index));
357 | | }
358 | |
359 | | /**
360 | | * @dev Return the entire set in an array
361 | | *
362 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
363 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
364 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function
365 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
366 | | */
367 | | function values(UintSet storage set) internal view returns (uint256[] memory) {
368 | | bytes32[] memory store = _values(set._inner);
369 | | uint256[] memory result;
370 | |
371 | | /// @solidity memory-safe-assembly
372 | | assembly {
373 | | result := store
374 | | }
375 | |
376 | | return result;
377 | | }
378 | | }
379 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/prb-math/contracts/PRBMath.sol
1 | | // SPDX-License-Identifier: Unlicense
2 | | pragma solidity >=0.8.4;
3 | |
4 | | /// @notice Emitted when the result overflows uint256.
5 | | error PRBMath__MulDivFixedPointOverflow(uint256 prod1);
6 | |
7 | | /// @notice Emitted when the result overflows uint256.
8 | | error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);
9 | |
10 | | /// @notice Emitted when one of the inputs is type(int256).min.
11 | | error PRBMath__MulDivSignedInputTooSmall();
12 | |
13 | | /// @notice Emitted when the intermediary absolute result overflows int256.
14 | | error PRBMath__MulDivSignedOverflow(uint256 rAbs);
15 | |
16 | | /// @notice Emitted when the input is MIN_SD59x18.
17 | | error PRBMathSD59x18__AbsInputTooSmall();
18 | |
19 | | /// @notice Emitted when ceiling a number overflows SD59x18.
20 | | error PRBMathSD59x18__CeilOverflow(int256 x);
21 | |
22 | | /// @notice Emitted when one of the inputs is MIN_SD59x18.
23 | | error PRBMathSD59x18__DivInputTooSmall();
24 | |
25 | | /// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
26 | | error PRBMathSD59x18__DivOverflow(uint256 rAbs);
27 | |
28 | | /// @notice Emitted when the input is greater than 133.084258667509499441.
29 | | error PRBMathSD59x18__ExpInputTooBig(int256 x);
30 | |
31 | | /// @notice Emitted when the input is greater than 192.
32 | | error PRBMathSD59x18__Exp2InputTooBig(int256 x);
33 | |
34 | | /// @notice Emitted when flooring a number underflows SD59x18.
35 | | error PRBMathSD59x18__FloorUnderflow(int256 x);
36 | |
37 | | /// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
38 | | error PRBMathSD59x18__FromIntOverflow(int256 x);
39 | |
40 | | /// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
41 | | error PRBMathSD59x18__FromIntUnderflow(int256 x);
42 | |
43 | | /// @notice Emitted when the product of the inputs is negative.
44 | | error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);
45 | |
46 | | /// @notice Emitted when multiplying the inputs overflows SD59x18.
47 | | error PRBMathSD59x18__GmOverflow(int256 x, int256 y);
48 | |
49 | | /// @notice Emitted when the input is less than or equal to zero.
50 | | error PRBMathSD59x18__LogInputTooSmall(int256 x);
51 | |
52 | | /// @notice Emitted when one of the inputs is MIN_SD59x18.
53 | | error PRBMathSD59x18__MulInputTooSmall();
54 | |
55 | | /// @notice Emitted when the intermediary absolute result overflows SD59x18.
56 | | error PRBMathSD59x18__MulOverflow(uint256 rAbs);
57 | |
58 | | /// @notice Emitted when the intermediary absolute result overflows SD59x18.
59 | | error PRBMathSD59x18__PowuOverflow(uint256 rAbs);
60 | |
61 | | /// @notice Emitted when the input is negative.
62 | | error PRBMathSD59x18__SqrtNegativeInput(int256 x);
63 | |
64 | | /// @notice Emitted when the calculating the square root overflows SD59x18.
65 | | error PRBMathSD59x18__SqrtOverflow(int256 x);
66 | |
67 | | /// @notice Emitted when addition overflows UD60x18.
68 | | error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);
69 | |
70 | | /// @notice Emitted when ceiling a number overflows UD60x18.
71 | | error PRBMathUD60x18__CeilOverflow(uint256 x);
72 | |
73 | | /// @notice Emitted when the input is greater than 133.084258667509499441.
74 | | error PRBMathUD60x18__ExpInputTooBig(uint256 x);
75 | |
76 | | /// @notice Emitted when the input is greater than 192.
77 | | error PRBMathUD60x18__Exp2InputTooBig(uint256 x);
78 | |
79 | | /// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
80 | | error PRBMathUD60x18__FromUintOverflow(uint256 x);
81 | |
82 | | /// @notice Emitted when multiplying the inputs overflows UD60x18.
83 | | error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);
84 | |
85 | | /// @notice Emitted when the input is less than 1.
86 | | error PRBMathUD60x18__LogInputTooSmall(uint256 x);
87 | |
88 | | /// @notice Emitted when the calculating the square root overflows UD60x18.
89 | | error PRBMathUD60x18__SqrtOverflow(uint256 x);
90 | |
91 | | /// @notice Emitted when subtraction underflows UD60x18.
92 | | error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);
93 | |
94 | | /// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
95 | | /// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
96 | | /// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
97 | * | library PRBMath {
98 | | /// STRUCTS ///
99 | |
100 | | struct SD59x18 {
101 | | int256 value;
102 | | }
103 | |
104 | | struct UD60x18 {
105 | | uint256 value;
106 | | }
107 | |
108 | | /// STORAGE ///
109 | |
110 | | /// @dev How many trailing decimals can be represented.
111 | * | uint256 internal constant SCALE = 1e18;
112 | |
113 | | /// @dev Largest power of two divisor of SCALE.
114 | | uint256 internal constant SCALE_LPOTD = 262144;
115 | |
116 | | /// @dev SCALE inverted mod 2^256.
117 | | uint256 internal constant SCALE_INVERSE =
118 | | 78156646155174841979727994598816262306175212592076161876661_508869554232690281;
119 | |
120 | | /// FUNCTIONS ///
121 | |
122 | | /// @notice Calculates the binary exponent of x using the binary fraction method.
123 | | /// @dev Has to use 192.64-bit fixed-point numbers.
124 | | /// See https://ethereum.stackexchange.com/a/96594/24693.
125 | | /// @param x The exponent as an unsigned 192.64-bit fixed-point number.
126 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
127 | * | function exp2(uint256 x) internal pure returns (uint256 result) {
128 | | unchecked {
129 | | // Start from 0.5 in the 192.64-bit fixed-point format.
130 | * | result = 0x800000000000000000000000000000000000000000000000;
131 | |
132 | | // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
133 | | // because the initial result is 2^191 and all magic factors are less than 2^65.
134 | * | if (x & 0x8000000000000000 > 0) {
135 | | result = (result * 0x16A09E667F3BCC909) >> 64;
136 | | }
137 | * | if (x & 0x4000000000000000 > 0) {
138 | | result = (result * 0x1306FE0A31B7152DF) >> 64;
139 | | }
140 | * | if (x & 0x2000000000000000 > 0) {
141 | | result = (result * 0x1172B83C7D517ADCE) >> 64;
142 | | }
143 | * | if (x & 0x1000000000000000 > 0) {
144 | | result = (result * 0x10B5586CF9890F62A) >> 64;
145 | | }
146 | * | if (x & 0x800000000000000 > 0) {
147 | | result = (result * 0x1059B0D31585743AE) >> 64;
148 | | }
149 | * | if (x & 0x400000000000000 > 0) {
150 | | result = (result * 0x102C9A3E778060EE7) >> 64;
151 | | }
152 | * | if (x & 0x200000000000000 > 0) {
153 | | result = (result * 0x10163DA9FB33356D8) >> 64;
154 | | }
155 | * | if (x & 0x100000000000000 > 0) {
156 | | result = (result * 0x100B1AFA5ABCBED61) >> 64;
157 | | }
158 | * | if (x & 0x80000000000000 > 0) {
159 | | result = (result * 0x10058C86DA1C09EA2) >> 64;
160 | | }
161 | * | if (x & 0x40000000000000 > 0) {
162 | | result = (result * 0x1002C605E2E8CEC50) >> 64;
163 | | }
164 | * | if (x & 0x20000000000000 > 0) {
165 | | result = (result * 0x100162F3904051FA1) >> 64;
166 | | }
167 | * | if (x & 0x10000000000000 > 0) {
168 | | result = (result * 0x1000B175EFFDC76BA) >> 64;
169 | | }
170 | * | if (x & 0x8000000000000 > 0) {
171 | | result = (result * 0x100058BA01FB9F96D) >> 64;
172 | | }
173 | * | if (x & 0x4000000000000 > 0) {
174 | | result = (result * 0x10002C5CC37DA9492) >> 64;
175 | | }
176 | * | if (x & 0x2000000000000 > 0) {
177 | | result = (result * 0x1000162E525EE0547) >> 64;
178 | | }
179 | * | if (x & 0x1000000000000 > 0) {
180 | | result = (result * 0x10000B17255775C04) >> 64;
181 | | }
182 | * | if (x & 0x800000000000 > 0) {
183 | | result = (result * 0x1000058B91B5BC9AE) >> 64;
184 | | }
185 | * | if (x & 0x400000000000 > 0) {
186 | | result = (result * 0x100002C5C89D5EC6D) >> 64;
187 | | }
188 | * | if (x & 0x200000000000 > 0) {
189 | | result = (result * 0x10000162E43F4F831) >> 64;
190 | | }
191 | * | if (x & 0x100000000000 > 0) {
192 | | result = (result * 0x100000B1721BCFC9A) >> 64;
193 | | }
194 | * | if (x & 0x80000000000 > 0) {
195 | | result = (result * 0x10000058B90CF1E6E) >> 64;
196 | | }
197 | * | if (x & 0x40000000000 > 0) {
198 | | result = (result * 0x1000002C5C863B73F) >> 64;
199 | | }
200 | * | if (x & 0x20000000000 > 0) {
201 | | result = (result * 0x100000162E430E5A2) >> 64;
202 | | }
203 | * | if (x & 0x10000000000 > 0) {
204 | | result = (result * 0x1000000B172183551) >> 64;
205 | | }
206 | * | if (x & 0x8000000000 > 0) {
207 | | result = (result * 0x100000058B90C0B49) >> 64;
208 | | }
209 | * | if (x & 0x4000000000 > 0) {
210 | | result = (result * 0x10000002C5C8601CC) >> 64;
211 | | }
212 | * | if (x & 0x2000000000 > 0) {
213 | | result = (result * 0x1000000162E42FFF0) >> 64;
214 | | }
215 | * | if (x & 0x1000000000 > 0) {
216 | | result = (result * 0x10000000B17217FBB) >> 64;
217 | | }
218 | * | if (x & 0x800000000 > 0) {
219 | | result = (result * 0x1000000058B90BFCE) >> 64;
220 | | }
221 | * | if (x & 0x400000000 > 0) {
222 | | result = (result * 0x100000002C5C85FE3) >> 64;
223 | | }
224 | * | if (x & 0x200000000 > 0) {
225 | | result = (result * 0x10000000162E42FF1) >> 64;
226 | | }
227 | * | if (x & 0x100000000 > 0) {
228 | | result = (result * 0x100000000B17217F8) >> 64;
229 | | }
230 | * | if (x & 0x80000000 > 0) {
231 | | result = (result * 0x10000000058B90BFC) >> 64;
232 | | }
233 | * | if (x & 0x40000000 > 0) {
234 | | result = (result * 0x1000000002C5C85FE) >> 64;
235 | | }
236 | * | if (x & 0x20000000 > 0) {
237 | | result = (result * 0x100000000162E42FF) >> 64;
238 | | }
239 | * | if (x & 0x10000000 > 0) {
240 | | result = (result * 0x1000000000B17217F) >> 64;
241 | | }
242 | * | if (x & 0x8000000 > 0) {
243 | | result = (result * 0x100000000058B90C0) >> 64;
244 | | }
245 | * | if (x & 0x4000000 > 0) {
246 | | result = (result * 0x10000000002C5C860) >> 64;
247 | | }
248 | * | if (x & 0x2000000 > 0) {
249 | | result = (result * 0x1000000000162E430) >> 64;
250 | | }
251 | * | if (x & 0x1000000 > 0) {
252 | | result = (result * 0x10000000000B17218) >> 64;
253 | | }
254 | * | if (x & 0x800000 > 0) {
255 | | result = (result * 0x1000000000058B90C) >> 64;
256 | | }
257 | * | if (x & 0x400000 > 0) {
258 | | result = (result * 0x100000000002C5C86) >> 64;
259 | | }
260 | * | if (x & 0x200000 > 0) {
261 | | result = (result * 0x10000000000162E43) >> 64;
262 | | }
263 | * | if (x & 0x100000 > 0) {
264 | | result = (result * 0x100000000000B1721) >> 64;
265 | | }
266 | * | if (x & 0x80000 > 0) {
267 | | result = (result * 0x10000000000058B91) >> 64;
268 | | }
269 | * | if (x & 0x40000 > 0) {
270 | | result = (result * 0x1000000000002C5C8) >> 64;
271 | | }
272 | * | if (x & 0x20000 > 0) {
273 | | result = (result * 0x100000000000162E4) >> 64;
274 | | }
275 | * | if (x & 0x10000 > 0) {
276 | | result = (result * 0x1000000000000B172) >> 64;
277 | | }
278 | * | if (x & 0x8000 > 0) {
279 | | result = (result * 0x100000000000058B9) >> 64;
280 | | }
281 | * | if (x & 0x4000 > 0) {
282 | | result = (result * 0x10000000000002C5D) >> 64;
283 | | }
284 | * | if (x & 0x2000 > 0) {
285 | | result = (result * 0x1000000000000162E) >> 64;
286 | | }
287 | * | if (x & 0x1000 > 0) {
288 | | result = (result * 0x10000000000000B17) >> 64;
289 | | }
290 | * | if (x & 0x800 > 0) {
291 | | result = (result * 0x1000000000000058C) >> 64;
292 | | }
293 | * | if (x & 0x400 > 0) {
294 | | result = (result * 0x100000000000002C6) >> 64;
295 | | }
296 | * | if (x & 0x200 > 0) {
297 | | result = (result * 0x10000000000000163) >> 64;
298 | | }
299 | * | if (x & 0x100 > 0) {
300 | | result = (result * 0x100000000000000B1) >> 64;
301 | | }
302 | * | if (x & 0x80 > 0) {
303 | | result = (result * 0x10000000000000059) >> 64;
304 | | }
305 | * | if (x & 0x40 > 0) {
306 | | result = (result * 0x1000000000000002C) >> 64;
307 | | }
308 | * | if (x & 0x20 > 0) {
309 | | result = (result * 0x10000000000000016) >> 64;
310 | | }
311 | * | if (x & 0x10 > 0) {
312 | | result = (result * 0x1000000000000000B) >> 64;
313 | | }
314 | * | if (x & 0x8 > 0) {
315 | | result = (result * 0x10000000000000006) >> 64;
316 | | }
317 | * | if (x & 0x4 > 0) {
318 | | result = (result * 0x10000000000000003) >> 64;
319 | | }
320 | * | if (x & 0x2 > 0) {
321 | | result = (result * 0x10000000000000001) >> 64;
322 | | }
323 | * | if (x & 0x1 > 0) {
324 | | result = (result * 0x10000000000000001) >> 64;
325 | | }
326 | |
327 | | // We're doing two things at the same time:
328 | | //
329 | | // 1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
330 | | // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
331 | | // rather than 192.
332 | | // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.
333 | | //
334 | | // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
335 | * | result *= SCALE;
336 | * | result >>= (191 - (x >> 64));
337 | | }
338 | | }
339 | |
340 | | /// @notice Finds the zero-based index of the first one in the binary representation of x.
341 | | /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
342 | | /// @param x The uint256 number for which to find the index of the most significant bit.
343 | | /// @return msb The index of the most significant bit as an uint256.
344 | * | function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
345 | * | if (x >= 2**128) {
346 | | x >>= 128;
347 | | msb += 128;
348 | | }
349 | * | if (x >= 2**64) {
350 | | x >>= 64;
351 | | msb += 64;
352 | | }
353 | * | if (x >= 2**32) {
354 | * | x >>= 32;
355 | * | msb += 32;
356 | | }
357 | * | if (x >= 2**16) {
358 | * | x >>= 16;
359 | * | msb += 16;
360 | | }
361 | * | if (x >= 2**8) {
362 | * | x >>= 8;
363 | * | msb += 8;
364 | | }
365 | * | if (x >= 2**4) {
366 | * | x >>= 4;
367 | * | msb += 4;
368 | | }
369 | * | if (x >= 2**2) {
370 | * | x >>= 2;
371 | * | msb += 2;
372 | | }
373 | * | if (x >= 2**1) {
374 | | // No need to shift x any more.
375 | * | msb += 1;
376 | | }
377 | | }
378 | |
379 | | /// @notice Calculates floor(x*y÷denominator) with full precision.
380 | | ///
381 | | /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
382 | | ///
383 | | /// Requirements:
384 | | /// - The denominator cannot be zero.
385 | | /// - The result must fit within uint256.
386 | | ///
387 | | /// Caveats:
388 | | /// - This function does not work with fixed-point numbers.
389 | | ///
390 | | /// @param x The multiplicand as an uint256.
391 | | /// @param y The multiplier as an uint256.
392 | | /// @param denominator The divisor as an uint256.
393 | | /// @return result The result as an uint256.
394 | | function mulDiv(
395 | | uint256 x,
396 | | uint256 y,
397 | | uint256 denominator
398 | | ) internal pure returns (uint256 result) {
399 | | // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
400 | | // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
401 | | // variables such that product = prod1 * 2^256 + prod0.
402 | | uint256 prod0; // Least significant 256 bits of the product
403 | | uint256 prod1; // Most significant 256 bits of the product
404 | | assembly {
405 | | let mm := mulmod(x, y, not(0))
406 | | prod0 := mul(x, y)
407 | | prod1 := sub(sub(mm, prod0), lt(mm, prod0))
408 | | }
409 | |
410 | | // Handle non-overflow cases, 256 by 256 division.
411 | | if (prod1 == 0) {
412 | | unchecked {
413 | | result = prod0 / denominator;
414 | | }
415 | | return result;
416 | | }
417 | |
418 | | // Make sure the result is less than 2^256. Also prevents denominator == 0.
419 | | if (prod1 >= denominator) {
420 | | revert PRBMath__MulDivOverflow(prod1, denominator);
421 | | }
422 | |
423 | | ///////////////////////////////////////////////
424 | | // 512 by 256 division.
425 | | ///////////////////////////////////////////////
426 | |
427 | | // Make division exact by subtracting the remainder from [prod1 prod0].
428 | | uint256 remainder;
429 | | assembly {
430 | | // Compute remainder using mulmod.
431 | | remainder := mulmod(x, y, denominator)
432 | |
433 | | // Subtract 256 bit number from 512 bit number.
434 | | prod1 := sub(prod1, gt(remainder, prod0))
435 | | prod0 := sub(prod0, remainder)
436 | | }
437 | |
438 | | // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
439 | | // See https://cs.stackexchange.com/q/138556/92363.
440 | | unchecked {
441 | | // Does not overflow because the denominator cannot be zero at this stage in the function.
442 | | uint256 lpotdod = denominator & (~denominator + 1);
443 | | assembly {
444 | | // Divide denominator by lpotdod.
445 | | denominator := div(denominator, lpotdod)
446 | |
447 | | // Divide [prod1 prod0] by lpotdod.
448 | | prod0 := div(prod0, lpotdod)
449 | |
450 | | // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
451 | | lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
452 | | }
453 | |
454 | | // Shift in bits from prod1 into prod0.
455 | | prod0 |= prod1 * lpotdod;
456 | |
457 | | // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
458 | | // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
459 | | // four bits. That is, denominator * inv = 1 mod 2^4.
460 | | uint256 inverse = (3 * denominator) ^ 2;
461 | |
462 | | // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
463 | | // in modular arithmetic, doubling the correct bits in each step.
464 | | inverse *= 2 - denominator * inverse; // inverse mod 2^8
465 | | inverse *= 2 - denominator * inverse; // inverse mod 2^16
466 | | inverse *= 2 - denominator * inverse; // inverse mod 2^32
467 | | inverse *= 2 - denominator * inverse; // inverse mod 2^64
468 | | inverse *= 2 - denominator * inverse; // inverse mod 2^128
469 | | inverse *= 2 - denominator * inverse; // inverse mod 2^256
470 | |
471 | | // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
472 | | // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
473 | | // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
474 | | // is no longer required.
475 | | result = prod0 * inverse;
476 | | return result;
477 | | }
478 | | }
479 | |
480 | | /// @notice Calculates floor(x*y÷1e18) with full precision.
481 | | ///
482 | | /// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
483 | | /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
484 | | /// being rounded to 1e-18. See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
485 | | ///
486 | | /// Requirements:
487 | | /// - The result must fit within uint256.
488 | | ///
489 | | /// Caveats:
490 | | /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
491 | | /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
492 | | /// 1. x * y = type(uint256).max * SCALE
493 | | /// 2. (x * y) % SCALE >= SCALE / 2
494 | | ///
495 | | /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
496 | | /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
497 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
498 | * | function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
499 | * | uint256 prod0;
500 | * | uint256 prod1;
501 | * | assembly {
502 | * | let mm := mulmod(x, y, not(0))
503 | * | prod0 := mul(x, y)
504 | * | prod1 := sub(sub(mm, prod0), lt(mm, prod0))
505 | | }
506 | |
507 | * | if (prod1 >= SCALE) {
508 | | revert PRBMath__MulDivFixedPointOverflow(prod1);
509 | | }
510 | |
511 | * | uint256 remainder;
512 | * | uint256 roundUpUnit;
513 | | assembly {
514 | * | remainder := mulmod(x, y, SCALE)
515 | * | roundUpUnit := gt(remainder, 499999999999999999)
516 | | }
517 | |
518 | * | if (prod1 == 0) {
519 | | unchecked {
520 | * | result = (prod0 / SCALE) + roundUpUnit;
521 | * | return result;
522 | | }
523 | | }
524 | |
525 | | assembly {
526 | | result := add(
527 | | mul(
528 | | or(
529 | | div(sub(prod0, remainder), SCALE_LPOTD),
530 | | mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
531 | | ),
532 | | SCALE_INVERSE
533 | | ),
534 | | roundUpUnit
535 | | )
536 | | }
537 | | }
538 | |
539 | | /// @notice Calculates floor(x*y÷denominator) with full precision.
540 | | ///
541 | | /// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
542 | | ///
543 | | /// Requirements:
544 | | /// - None of the inputs can be type(int256).min.
545 | | /// - The result must fit within int256.
546 | | ///
547 | | /// @param x The multiplicand as an int256.
548 | | /// @param y The multiplier as an int256.
549 | | /// @param denominator The divisor as an int256.
550 | | /// @return result The result as an int256.
551 | | function mulDivSigned(
552 | | int256 x,
553 | | int256 y,
554 | | int256 denominator
555 | | ) internal pure returns (int256 result) {
556 | | if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
557 | | revert PRBMath__MulDivSignedInputTooSmall();
558 | | }
559 | |
560 | | // Get hold of the absolute values of x, y and the denominator.
561 | | uint256 ax;
562 | | uint256 ay;
563 | | uint256 ad;
564 | | unchecked {
565 | | ax = x < 0 ? uint256(-x) : uint256(x);
566 | | ay = y < 0 ? uint256(-y) : uint256(y);
567 | | ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
568 | | }
569 | |
570 | | // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
571 | | uint256 rAbs = mulDiv(ax, ay, ad);
572 | | if (rAbs > uint256(type(int256).max)) {
573 | | revert PRBMath__MulDivSignedOverflow(rAbs);
574 | | }
575 | |
576 | | // Get the signs of x, y and the denominator.
577 | | uint256 sx;
578 | | uint256 sy;
579 | | uint256 sd;
580 | | assembly {
581 | | sx := sgt(x, sub(0, 1))
582 | | sy := sgt(y, sub(0, 1))
583 | | sd := sgt(denominator, sub(0, 1))
584 | | }
585 | |
586 | | // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
587 | | // If yes, the result should be negative.
588 | | result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
589 | | }
590 | |
591 | | /// @notice Calculates the square root of x, rounding down.
592 | | /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
593 | | ///
594 | | /// Caveats:
595 | | /// - This function does not work with fixed-point numbers.
596 | | ///
597 | | /// @param x The uint256 number for which to calculate the square root.
598 | | /// @return result The result as an uint256.
599 | | function sqrt(uint256 x) internal pure returns (uint256 result) {
600 | | if (x == 0) {
601 | | return 0;
602 | | }
603 | |
604 | | // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).
605 | | uint256 xAux = uint256(x);
606 | | result = 1;
607 | | if (xAux >= 0x100000000000000000000000000000000) {
608 | | xAux >>= 128;
609 | | result <<= 64;
610 | | }
611 | | if (xAux >= 0x10000000000000000) {
612 | | xAux >>= 64;
613 | | result <<= 32;
614 | | }
615 | | if (xAux >= 0x100000000) {
616 | | xAux >>= 32;
617 | | result <<= 16;
618 | | }
619 | | if (xAux >= 0x10000) {
620 | | xAux >>= 16;
621 | | result <<= 8;
622 | | }
623 | | if (xAux >= 0x100) {
624 | | xAux >>= 8;
625 | | result <<= 4;
626 | | }
627 | | if (xAux >= 0x10) {
628 | | xAux >>= 4;
629 | | result <<= 2;
630 | | }
631 | | if (xAux >= 0x8) {
632 | | result <<= 1;
633 | | }
634 | |
635 | | // The operations can never overflow because the result is max 2^127 when it enters this block.
636 | | unchecked {
637 | | result = (result + x / result) >> 1;
638 | | result = (result + x / result) >> 1;
639 | | result = (result + x / result) >> 1;
640 | | result = (result + x / result) >> 1;
641 | | result = (result + x / result) >> 1;
642 | | result = (result + x / result) >> 1;
643 | | result = (result + x / result) >> 1; // Seven iterations should be enough
644 | | uint256 roundedDownResult = x / result;
645 | | return result >= roundedDownResult ? roundedDownResult : result;
646 | | }
647 | | }
648 | | }
649 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/prb-math/contracts/PRBMathUD60x18.sol
1 | | // SPDX-License-Identifier: Unlicense
2 | | pragma solidity >=0.8.4;
3 | |
4 | | import "./PRBMath.sol";
5 | |
6 | | /// @title PRBMathUD60x18
7 | | /// @author Paul Razvan Berg
8 | | /// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18
9 | | /// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60
10 | | /// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the
11 | | /// maximum values permitted by the Solidity type uint256.
12 | * | library PRBMathUD60x18 {
13 | | /// @dev Half the SCALE number.
14 | * | uint256 internal constant HALF_SCALE = 5e17;
15 | |
16 | | /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.
17 | | uint256 internal constant LOG2_E = 1_442695040888963407;
18 | |
19 | | /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.
20 | | uint256 internal constant MAX_UD60x18 =
21 | | 115792089237316195423570985008687907853269984665640564039457_584007913129639935;
22 | |
23 | | /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.
24 | | uint256 internal constant MAX_WHOLE_UD60x18 =
25 | | 115792089237316195423570985008687907853269984665640564039457_000000000000000000;
26 | |
27 | | /// @dev How many trailing decimals can be represented.
28 | * | uint256 internal constant SCALE = 1e18;
29 | |
30 | | /// @notice Calculates the arithmetic average of x and y, rounding down.
31 | | /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
32 | | /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
33 | | /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.
34 | | function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {
35 | | // The operations can never overflow.
36 | | unchecked {
37 | | // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need
38 | | // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.
39 | | result = (x >> 1) + (y >> 1) + (x & y & 1);
40 | | }
41 | | }
42 | |
43 | | /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.
44 | | ///
45 | | /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
46 | | /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
47 | | ///
48 | | /// Requirements:
49 | | /// - x must be less than or equal to MAX_WHOLE_UD60x18.
50 | | ///
51 | | /// @param x The unsigned 60.18-decimal fixed-point number to ceil.
52 | | /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.
53 | | function ceil(uint256 x) internal pure returns (uint256 result) {
54 | | if (x > MAX_WHOLE_UD60x18) {
55 | | revert PRBMathUD60x18__CeilOverflow(x);
56 | | }
57 | | assembly {
58 | | // Equivalent to "x % SCALE" but faster.
59 | | let remainder := mod(x, SCALE)
60 | |
61 | | // Equivalent to "SCALE - remainder" but faster.
62 | | let delta := sub(SCALE, remainder)
63 | |
64 | | // Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster.
65 | | result := add(x, mul(delta, gt(remainder, 0)))
66 | | }
67 | | }
68 | |
69 | | /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.
70 | | ///
71 | | /// @dev Uses mulDiv to enable overflow-safe multiplication and division.
72 | | ///
73 | | /// Requirements:
74 | | /// - The denominator cannot be zero.
75 | | ///
76 | | /// @param x The numerator as an unsigned 60.18-decimal fixed-point number.
77 | | /// @param y The denominator as an unsigned 60.18-decimal fixed-point number.
78 | | /// @param result The quotient as an unsigned 60.18-decimal fixed-point number.
79 | | function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
80 | | result = PRBMath.mulDiv(x, SCALE, y);
81 | | }
82 | |
83 | | /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.
84 | | /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).
85 | | function e() internal pure returns (uint256 result) {
86 | | result = 2_718281828459045235;
87 | | }
88 | |
89 | | /// @notice Calculates the natural exponent of x.
90 | | ///
91 | | /// @dev Based on the insight that e^x = 2^(x * log2(e)).
92 | | ///
93 | | /// Requirements:
94 | | /// - All from "log2".
95 | | /// - x must be less than 133.084258667509499441.
96 | | ///
97 | | /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
98 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
99 | | function exp(uint256 x) internal pure returns (uint256 result) {
100 | | // Without this check, the value passed to "exp2" would be greater than 192.
101 | | if (x >= 133_084258667509499441) {
102 | | revert PRBMathUD60x18__ExpInputTooBig(x);
103 | | }
104 | |
105 | | // Do the fixed-point multiplication inline to save gas.
106 | | unchecked {
107 | | uint256 doubleScaleProduct = x * LOG2_E;
108 | | result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
109 | | }
110 | | }
111 | |
112 | | /// @notice Calculates the binary exponent of x using the binary fraction method.
113 | | ///
114 | | /// @dev See https://ethereum.stackexchange.com/q/79903/24693.
115 | | ///
116 | | /// Requirements:
117 | | /// - x must be 192 or less.
118 | | /// - The result must fit within MAX_UD60x18.
119 | | ///
120 | | /// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
121 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
122 | * | function exp2(uint256 x) internal pure returns (uint256 result) {
123 | | // 2^192 doesn't fit within the 192.64-bit format used internally in this function.
124 | * | if (x >= 192e18) {
125 | | revert PRBMathUD60x18__Exp2InputTooBig(x);
126 | | }
127 | |
128 | * | unchecked {
129 | | // Convert x to the 192.64-bit fixed-point format.
130 | * | uint256 x192x64 = (x << 64) / SCALE;
131 | |
132 | | // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.
133 | * | result = PRBMath.exp2(x192x64);
134 | | }
135 | | }
136 | |
137 | | /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.
138 | | /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
139 | | /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
140 | | /// @param x The unsigned 60.18-decimal fixed-point number to floor.
141 | | /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.
142 | | function floor(uint256 x) internal pure returns (uint256 result) {
143 | | assembly {
144 | | // Equivalent to "x % SCALE" but faster.
145 | | let remainder := mod(x, SCALE)
146 | |
147 | | // Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster.
148 | | result := sub(x, mul(remainder, gt(remainder, 0)))
149 | | }
150 | | }
151 | |
152 | | /// @notice Yields the excess beyond the floor of x.
153 | | /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.
154 | | /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.
155 | | /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.
156 | | function frac(uint256 x) internal pure returns (uint256 result) {
157 | | assembly {
158 | | result := mod(x, SCALE)
159 | | }
160 | | }
161 | |
162 | | /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.
163 | | ///
164 | | /// @dev Requirements:
165 | | /// - x must be less than or equal to MAX_UD60x18 divided by SCALE.
166 | | ///
167 | | /// @param x The basic integer to convert.
168 | | /// @param result The same number in unsigned 60.18-decimal fixed-point representation.
169 | | function fromUint(uint256 x) internal pure returns (uint256 result) {
170 | | unchecked {
171 | | if (x > MAX_UD60x18 / SCALE) {
172 | | revert PRBMathUD60x18__FromUintOverflow(x);
173 | | }
174 | | result = x * SCALE;
175 | | }
176 | | }
177 | |
178 | | /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.
179 | | ///
180 | | /// @dev Requirements:
181 | | /// - x * y must fit within MAX_UD60x18, lest it overflows.
182 | | ///
183 | | /// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
184 | | /// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
185 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
186 | | function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {
187 | | if (x == 0) {
188 | | return 0;
189 | | }
190 | |
191 | | unchecked {
192 | | // Checking for overflow this way is faster than letting Solidity do it.
193 | | uint256 xy = x * y;
194 | | if (xy / x != y) {
195 | | revert PRBMathUD60x18__GmOverflow(x, y);
196 | | }
197 | |
198 | | // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE
199 | | // during multiplication. See the comments within the "sqrt" function.
200 | | result = PRBMath.sqrt(xy);
201 | | }
202 | | }
203 | |
204 | | /// @notice Calculates 1 / x, rounding toward zero.
205 | | ///
206 | | /// @dev Requirements:
207 | | /// - x cannot be zero.
208 | | ///
209 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.
210 | | /// @return result The inverse as an unsigned 60.18-decimal fixed-point number.
211 | | function inv(uint256 x) internal pure returns (uint256 result) {
212 | | unchecked {
213 | | // 1e36 is SCALE * SCALE.
214 | | result = 1e36 / x;
215 | | }
216 | | }
217 | |
218 | | /// @notice Calculates the natural logarithm of x.
219 | | ///
220 | | /// @dev Based on the insight that ln(x) = log2(x) / log2(e).
221 | | ///
222 | | /// Requirements:
223 | | /// - All from "log2".
224 | | ///
225 | | /// Caveats:
226 | | /// - All from "log2".
227 | | /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.
228 | | ///
229 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.
230 | | /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.
231 | | function ln(uint256 x) internal pure returns (uint256 result) {
232 | | // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)
233 | | // can return is 196205294292027477728.
234 | | unchecked {
235 | | result = (log2(x) * SCALE) / LOG2_E;
236 | | }
237 | | }
238 | |
239 | | /// @notice Calculates the common logarithm of x.
240 | | ///
241 | | /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
242 | | /// logarithm based on the insight that log10(x) = log2(x) / log2(10).
243 | | ///
244 | | /// Requirements:
245 | | /// - All from "log2".
246 | | ///
247 | | /// Caveats:
248 | | /// - All from "log2".
249 | | ///
250 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.
251 | | /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.
252 | | function log10(uint256 x) internal pure returns (uint256 result) {
253 | | if (x < SCALE) {
254 | | revert PRBMathUD60x18__LogInputTooSmall(x);
255 | | }
256 | |
257 | | // Note that the "mul" in this block is the assembly multiplication operation, not the "mul" function defined
258 | | // in this contract.
259 | | // prettier-ignore
260 | | assembly {
261 | | switch x
262 | | case 1 { result := mul(SCALE, sub(0, 18)) }
263 | | case 10 { result := mul(SCALE, sub(1, 18)) }
264 | | case 100 { result := mul(SCALE, sub(2, 18)) }
265 | | case 1000 { result := mul(SCALE, sub(3, 18)) }
266 | | case 10000 { result := mul(SCALE, sub(4, 18)) }
267 | | case 100000 { result := mul(SCALE, sub(5, 18)) }
268 | | case 1000000 { result := mul(SCALE, sub(6, 18)) }
269 | | case 10000000 { result := mul(SCALE, sub(7, 18)) }
270 | | case 100000000 { result := mul(SCALE, sub(8, 18)) }
271 | | case 1000000000 { result := mul(SCALE, sub(9, 18)) }
272 | | case 10000000000 { result := mul(SCALE, sub(10, 18)) }
273 | | case 100000000000 { result := mul(SCALE, sub(11, 18)) }
274 | | case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
275 | | case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
276 | | case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
277 | | case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
278 | | case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
279 | | case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
280 | | case 1000000000000000000 { result := 0 }
281 | | case 10000000000000000000 { result := SCALE }
282 | | case 100000000000000000000 { result := mul(SCALE, 2) }
283 | | case 1000000000000000000000 { result := mul(SCALE, 3) }
284 | | case 10000000000000000000000 { result := mul(SCALE, 4) }
285 | | case 100000000000000000000000 { result := mul(SCALE, 5) }
286 | | case 1000000000000000000000000 { result := mul(SCALE, 6) }
287 | | case 10000000000000000000000000 { result := mul(SCALE, 7) }
288 | | case 100000000000000000000000000 { result := mul(SCALE, 8) }
289 | | case 1000000000000000000000000000 { result := mul(SCALE, 9) }
290 | | case 10000000000000000000000000000 { result := mul(SCALE, 10) }
291 | | case 100000000000000000000000000000 { result := mul(SCALE, 11) }
292 | | case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
293 | | case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
294 | | case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
295 | | case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
296 | | case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
297 | | case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
298 | | case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
299 | | case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
300 | | case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
301 | | case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
302 | | case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
303 | | case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
304 | | case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
305 | | case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
306 | | case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
307 | | case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
308 | | case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
309 | | case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
310 | | case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
311 | | case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
312 | | case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
313 | | case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
314 | | case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
315 | | case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
316 | | case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
317 | | case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
318 | | case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
319 | | case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
320 | | case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
321 | | case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
322 | | case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
323 | | case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
324 | | case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
325 | | case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
326 | | case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
327 | | case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
328 | | case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
329 | | case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
330 | | case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
331 | | case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
332 | | case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
333 | | case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
334 | | case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
335 | | case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
336 | | case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
337 | | case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
338 | | case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
339 | | case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }
340 | | default {
341 | | result := MAX_UD60x18
342 | | }
343 | | }
344 | |
345 | | if (result == MAX_UD60x18) {
346 | | // Do the fixed-point division inline to save gas. The denominator is log2(10).
347 | | unchecked {
348 | | result = (log2(x) * SCALE) / 3_321928094887362347;
349 | | }
350 | | }
351 | | }
352 | |
353 | | /// @notice Calculates the binary logarithm of x.
354 | | ///
355 | | /// @dev Based on the iterative approximation algorithm.
356 | | /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
357 | | ///
358 | | /// Requirements:
359 | | /// - x must be greater than or equal to SCALE, otherwise the result would be negative.
360 | | ///
361 | | /// Caveats:
362 | | /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
363 | | ///
364 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.
365 | | /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.
366 | * | function log2(uint256 x) internal pure returns (uint256 result) {
367 | * | if (x < SCALE) {
368 | | revert PRBMathUD60x18__LogInputTooSmall(x);
369 | | }
370 | * | unchecked {
371 | | // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).
372 | * | uint256 n = PRBMath.mostSignificantBit(x / SCALE);
373 | |
374 | | // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow
375 | | // because n is maximum 255 and SCALE is 1e18.
376 | * | result = n * SCALE;
377 | |
378 | | // This is y = x * 2^(-n).
379 | * | uint256 y = x >> n;
380 | |
381 | | // If y = 1, the fractional part is zero.
382 | * | if (y == SCALE) {
383 | * | return result;
384 | | }
385 | |
386 | | // Calculate the fractional part via the iterative approximation.
387 | | // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
388 | * | for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {
389 | * | y = (y * y) / SCALE;
390 | |
391 | | // Is y^2 > 2 and so in the range [2,4)?
392 | * | if (y >= 2 * SCALE) {
393 | | // Add the 2^(-m) factor to the logarithm.
394 | * | result += delta;
395 | |
396 | | // Corresponds to z/2 on Wikipedia.
397 | * | y >>= 1;
398 | | }
399 | | }
400 | | }
401 | | }
402 | |
403 | | /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal
404 | | /// fixed-point number.
405 | | /// @dev See the documentation for the "PRBMath.mulDivFixedPoint" function.
406 | | /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
407 | | /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
408 | | /// @return result The product as an unsigned 60.18-decimal fixed-point number.
409 | * | function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
410 | * | result = PRBMath.mulDivFixedPoint(x, y);
411 | | }
412 | |
413 | | /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.
414 | | function pi() internal pure returns (uint256 result) {
415 | | result = 3_141592653589793238;
416 | | }
417 | |
418 | | /// @notice Raises x to the power of y.
419 | | ///
420 | | /// @dev Based on the insight that x^y = 2^(log2(x) * y).
421 | | ///
422 | | /// Requirements:
423 | | /// - All from "exp2", "log2" and "mul".
424 | | ///
425 | | /// Caveats:
426 | | /// - All from "exp2", "log2" and "mul".
427 | | /// - Assumes 0^0 is 1.
428 | | ///
429 | | /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.
430 | | /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.
431 | | /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.
432 | * | function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {
433 | * | if (x == 0) {
434 | | result = y == 0 ? SCALE : uint256(0);
435 | | } else {
436 | * | result = exp2(mul(log2(x), y));
437 | | }
438 | | }
439 | |
440 | | /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the
441 | | /// famous algorithm "exponentiation by squaring".
442 | | ///
443 | | /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
444 | | ///
445 | | /// Requirements:
446 | | /// - The result must fit within MAX_UD60x18.
447 | | ///
448 | | /// Caveats:
449 | | /// - All from "mul".
450 | | /// - Assumes 0^0 is 1.
451 | | ///
452 | | /// @param x The base as an unsigned 60.18-decimal fixed-point number.
453 | | /// @param y The exponent as an uint256.
454 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number.
455 | | function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {
456 | | // Calculate the first iteration of the loop in advance.
457 | | result = y & 1 > 0 ? x : SCALE;
458 | |
459 | | // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
460 | | for (y >>= 1; y > 0; y >>= 1) {
461 | | x = PRBMath.mulDivFixedPoint(x, x);
462 | |
463 | | // Equivalent to "y % 2 == 1" but faster.
464 | | if (y & 1 > 0) {
465 | | result = PRBMath.mulDivFixedPoint(result, x);
466 | | }
467 | | }
468 | | }
469 | |
470 | | /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.
471 | | function scale() internal pure returns (uint256 result) {
472 | | result = SCALE;
473 | | }
474 | |
475 | | /// @notice Calculates the square root of x, rounding down.
476 | | /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
477 | | ///
478 | | /// Requirements:
479 | | /// - x must be less than MAX_UD60x18 / SCALE.
480 | | ///
481 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.
482 | | /// @return result The result as an unsigned 60.18-decimal fixed-point .
483 | | function sqrt(uint256 x) internal pure returns (uint256 result) {
484 | | unchecked {
485 | | if (x > MAX_UD60x18 / SCALE) {
486 | | revert PRBMathUD60x18__SqrtOverflow(x);
487 | | }
488 | | // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned
489 | | // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).
490 | | result = PRBMath.sqrt(x * SCALE);
491 | | }
492 | | }
493 | |
494 | | /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.
495 | | /// @param x The unsigned 60.18-decimal fixed-point number to convert.
496 | | /// @return result The same number in basic integer form.
497 | | function toUint(uint256 x) internal pure returns (uint256 result) {
498 | | unchecked {
499 | | result = x / SCALE;
500 | | }
501 | | }
502 | | }
503 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/adl/AdlUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../event/EventEmitter.sol";
7 | |
8 | | import "../order/OrderStoreUtils.sol";
9 | | import "../order/OrderEventUtils.sol";
10 | | import "../position/PositionUtils.sol";
11 | | import "../position/PositionStoreUtils.sol";
12 | | import "../nonce/NonceUtils.sol";
13 | | import "../callback/CallbackUtils.sol";
14 | |
15 | | // @title AdlUtils
16 | | // @dev Library to help with auto-deleveraging
17 | | // This is particularly for markets with an index token that is different from
18 | | // the long token
19 | | //
20 | | // For example, if there is a DOGE / USD perp market with ETH as the long token
21 | | // it would be possible for the price of DOGE to increase faster than the price of
22 | | // ETH
23 | | //
24 | | // In this scenario, profitable positions should be closed through ADL to ensure
25 | | // that the system remains fully solvent
26 | * | library AdlUtils {
27 | | using SafeCast for int256;
28 | | using Array for uint256[];
29 | | using Market for Market.Props;
30 | | using Position for Position.Props;
31 | |
32 | | using EventUtils for EventUtils.AddressItems;
33 | | using EventUtils for EventUtils.UintItems;
34 | | using EventUtils for EventUtils.IntItems;
35 | | using EventUtils for EventUtils.BoolItems;
36 | | using EventUtils for EventUtils.Bytes32Items;
37 | | using EventUtils for EventUtils.BytesItems;
38 | | using EventUtils for EventUtils.StringItems;
39 | |
40 | | // @dev CreateAdlOrderParams struct used in createAdlOrder to avoid stack
41 | | // too deep errors
42 | | //
43 | | // @param dataStore DataStore
44 | | // @param orderStore OrderStore
45 | | // @param account the account to reduce the position for
46 | | // @param market the position's market
47 | | // @param collateralToken the position's collateralToken
48 | | // @param isLong whether the position is long or short
49 | | // @param sizeDeltaUsd the size to reduce the position by
50 | | // @param updatedAtBlock the block to set the order's updatedAtBlock to
51 | | struct CreateAdlOrderParams {
52 | | DataStore dataStore;
53 | | EventEmitter eventEmitter;
54 | | address account;
55 | | address market;
56 | | address collateralToken;
57 | | bool isLong;
58 | | uint256 sizeDeltaUsd;
59 | | uint256 updatedAtBlock;
60 | | uint256 updatedAtTime;
61 | | }
62 | |
63 | | // @dev Multiple positions may need to be reduced to ensure that the pending
64 | | // profits does not exceed the allowed thresholds
65 | | //
66 | | // This automatic reduction of positions can only be done if the pool is in a state
67 | | // where auto-deleveraging is required
68 | | //
69 | | // This function checks the pending profit state and updates an isAdlEnabled
70 | | // flag to avoid having to repeatedly validate whether auto-deleveraging is required
71 | | //
72 | | // Once the pending profit has been reduced below the threshold this function can
73 | | // be called again to clear the flag
74 | | //
75 | | // The ADL check would be possible to do in AdlHandler.executeAdl as well
76 | | // but with that order keepers could use stale oracle prices to prove that
77 | | // an ADL state is possible
78 | | //
79 | | // Having this function allows any order keeper to disable ADL if prices
80 | | // have updated such that ADL is no longer needed
81 | | //
82 | | // @param dataStore DataStore
83 | | // @param eventEmitter EventEmitter
84 | | // @param oracle Oracle
85 | | // @param market address of the market to check
86 | | // @param isLong indicates whether to check the long or short side of the market
87 | * | function updateAdlState(
88 | | DataStore dataStore,
89 | | EventEmitter eventEmitter,
90 | | Oracle oracle,
91 | | address market,
92 | | bool isLong
93 | * | ) internal {
94 | * | uint256 latestAdlTime = getLatestAdlTime(dataStore, market, isLong);
95 | |
96 | * | if (oracle.maxTimestamp() < latestAdlTime) {
97 | | revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime);
98 | | }
99 | |
100 | * | Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market);
101 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, _market);
102 | | // if the MAX_PNL_FACTOR_FOR_ADL is set to be higher than MAX_PNL_FACTOR_FOR_WITHDRAWALS
103 | | // it is possible for a pool to be in a state where withdrawals and ADL is not allowed
104 | | // this is similar to the case where there is a large amount of open positions relative
105 | | // to the amount of tokens in the pool
106 | * | (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded(
107 | * | dataStore,
108 | * | _market,
109 | * | prices,
110 | * | isLong,
111 | | Keys.MAX_PNL_FACTOR_FOR_ADL
112 | | );
113 | |
114 | * | setIsAdlEnabled(dataStore, market, isLong, shouldEnableAdl);
115 | | // since the latest ADL at is always updated, an ADL keeper could
116 | | // continually cause the latest ADL time to be updated and prevent
117 | | // ADL orders from being executed, however, this may be preferrable
118 | | // over a case where stale prices could be used by ADL keepers
119 | | // to execute orders
120 | | // as such updating of the ADL time is allowed and it is expected
121 | | // that ADL keepers will keep this time updated so that latest prices
122 | | // will be used for ADL
123 | * | setLatestAdlAt(dataStore, market, isLong, Chain.currentTimestamp());
124 | |
125 | * | emitAdlStateUpdated(eventEmitter, market, isLong, pnlToPoolFactor, maxPnlFactor, shouldEnableAdl);
126 | | }
127 | |
128 | | // @dev Construct an ADL order
129 | | //
130 | | // A decrease order is used to reduce a profitable position
131 | | //
132 | | // @param params CreateAdlOrderParams
133 | | // @return the key of the created order
134 | * | function createAdlOrder(CreateAdlOrderParams memory params) internal returns (bytes32) {
135 | * | bytes32 positionKey = Position.getPositionKey(params.account, params.market, params.collateralToken, params.isLong);
136 | * | Position.Props memory position = PositionStoreUtils.get(params.dataStore, positionKey);
137 | |
138 | * | if (params.sizeDeltaUsd > position.sizeInUsd()) {
139 | | revert Errors.InvalidSizeDeltaForAdl(params.sizeDeltaUsd, position.sizeInUsd());
140 | | }
141 | |
142 | * | Order.Addresses memory addresses = Order.Addresses(
143 | * | params.account, // account
144 | * | params.account, // receiver
145 | * | params.account, // cancellationReceiver
146 | * | CallbackUtils.getSavedCallbackContract(params.dataStore, params.account, params.market), // callbackContract
147 | * | address(0), // uiFeeReceiver
148 | * | params.market, // market
149 | * | position.collateralToken(), // initialCollateralToken
150 | * | new address[](0) // swapPath
151 | | );
152 | |
153 | | // no slippage is set for this order, it may be preferrable for ADL orders
154 | | // to be executed, in case of large price impact, the user could be refunded
155 | | // through a protocol fund if required, this amount could later be claimed
156 | | // from the price impact pool, this claiming process should be added if
157 | | // required
158 | | //
159 | | // setting a maximum price impact that will work for majority of cases
160 | | // may also be challenging since the price impact would vary based on the
161 | | // amount of collateral being swapped
162 | | //
163 | | // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken
164 | | // because fees are calculated with reference to the collateral token
165 | | // fees are deducted from the output amount if the output token is the same as the
166 | | // collateral token
167 | | // swapping the pnl token to the collateral token helps to ensure fees can be paid
168 | | // using the realized profit
169 | * | Order.Numbers memory numbers = Order.Numbers(
170 | * | Order.OrderType.MarketDecrease, // orderType
171 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType
172 | * | params.sizeDeltaUsd, // sizeDeltaUsd
173 | * | 0, // initialCollateralDeltaAmount
174 | * | 0, // triggerPrice
175 | * | position.isLong() ? 0 : type(uint256).max, // acceptablePrice
176 | * | 0, // executionFee
177 | * | params.dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit
178 | * | 0, // minOutputAmount
179 | * | params.updatedAtBlock, // updatedAtBlock
180 | * | params.updatedAtTime // updatedAtTime
181 | | );
182 | |
183 | * | Order.Flags memory flags = Order.Flags(
184 | * | position.isLong(), // isLong
185 | * | true, // shouldUnwrapNativeToken
186 | * | false, // isFrozen
187 | * | false // autoCancel
188 | | );
189 | |
190 | * | Order.Props memory order = Order.Props(
191 | * | addresses,
192 | * | numbers,
193 | * | flags
194 | | );
195 | |
196 | * | bytes32 key = NonceUtils.getNextKey(params.dataStore);
197 | * | OrderStoreUtils.set(params.dataStore, key, order);
198 | |
199 | * | OrderEventUtils.emitOrderCreated(params.eventEmitter, key, order);
200 | |
201 | * | return key;
202 | | }
203 | |
204 | | // @dev validate if the requested ADL can be executed
205 | | //
206 | | // @param dataStore DataStore
207 | | // @param oracle Oracle
208 | | // @param market address of the market to check
209 | | // @param isLong indicates whether to check the long or short side of the market
210 | * | function validateAdl(
211 | | DataStore dataStore,
212 | | Oracle oracle,
213 | | address market,
214 | | bool isLong
215 | * | ) internal view {
216 | * | bool isAdlEnabled = AdlUtils.getIsAdlEnabled(dataStore, market, isLong);
217 | * | if (!isAdlEnabled) {
218 | * | revert Errors.AdlNotEnabled();
219 | | }
220 | |
221 | * | uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong);
222 | * | if (oracle.maxTimestamp() < latestAdlTime) {
223 | | revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime);
224 | | }
225 | | }
226 | |
227 | | // @dev get the latest time at which the ADL flag was updated
228 | | //
229 | | // @param dataStore DataStore
230 | | // @param market address of the market to check
231 | | // @param isLong indicates whether to check the long or short side of the market
232 | | //
233 | | // @return the latest time at which the ADL flag was updated
234 | * | function getLatestAdlTime(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
235 | * | return dataStore.getUint(Keys.latestAdlAtKey(market, isLong));
236 | | }
237 | |
238 | | // @dev set the latest time at which the ADL flag was updated
239 | | //
240 | | // @param dataStore DataStore
241 | | // @param market address of the market to check
242 | | // @param isLong indicates whether to check the long or short side of the market
243 | | // @param value the latest time value
244 | | //
245 | | // @return the latest time value
246 | * | function setLatestAdlAt(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {
247 | * | return dataStore.setUint(Keys.latestAdlAtKey(market, isLong), value);
248 | | }
249 | |
250 | | // @dev get whether ADL is enabled
251 | | //
252 | | // @param dataStore DataStore
253 | | // @param market address of the market to check
254 | | // @param isLong indicates whether to check the long or short side of the market
255 | | //
256 | | // @return whether ADL is enabled
257 | * | function getIsAdlEnabled(DataStore dataStore, address market, bool isLong) internal view returns (bool) {
258 | * | return dataStore.getBool(Keys.isAdlEnabledKey(market, isLong));
259 | | }
260 | |
261 | | // @dev set whether ADL is enabled
262 | | //
263 | | // @param dataStore DataStore
264 | | // @param market address of the market to check
265 | | // @param isLong indicates whether to check the long or short side of the market
266 | | // @param value whether ADL is enabled
267 | | //
268 | | // @return whether ADL is enabled
269 | * | function setIsAdlEnabled(DataStore dataStore, address market, bool isLong, bool value) internal returns (bool) {
270 | * | return dataStore.setBool(Keys.isAdlEnabledKey(market, isLong), value);
271 | | }
272 | |
273 | | // @dev emit ADL state update events
274 | | //
275 | | // @param eventEmitter EventEmitter
276 | | // @param market address of the market for the ADL state update
277 | | // @param isLong indicates the ADL state update is for the long or short side of the market
278 | | // @param pnlToPoolFactor the ratio of PnL to pool value
279 | | // @param maxPnlFactor the max PnL factor
280 | | // @param shouldEnableAdl whether ADL was enabled or disabled
281 | * | function emitAdlStateUpdated(
282 | | EventEmitter eventEmitter,
283 | | address market,
284 | | bool isLong,
285 | | int256 pnlToPoolFactor,
286 | | uint256 maxPnlFactor,
287 | | bool shouldEnableAdl
288 | * | ) internal {
289 | * | EventUtils.EventLogData memory eventData;
290 | |
291 | * | eventData.intItems.initItems(1);
292 | * | eventData.intItems.setItem(0, "pnlToPoolFactor", pnlToPoolFactor);
293 | |
294 | * | eventData.uintItems.initItems(1);
295 | * | eventData.uintItems.setItem(0, "maxPnlFactor", maxPnlFactor);
296 | |
297 | * | eventData.boolItems.initItems(2);
298 | * | eventData.boolItems.setItem(0, "isLong", isLong);
299 | * | eventData.boolItems.setItem(1, "shouldEnableAdl", shouldEnableAdl);
300 | |
301 | * | eventEmitter.emitEventLog1(
302 | | "AdlStateUpdated",
303 | * | Cast.toBytes32(market),
304 | * | eventData
305 | | );
306 | | }
307 | | }
308 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/bank/Bank.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7 | |
8 | | import "../token/TokenUtils.sol";
9 | | import "../role/RoleModule.sol";
10 | |
11 | | // @title Bank
12 | | // @dev Contract to handle storing and transferring of tokens
13 | | contract Bank is RoleModule {
14 | | using SafeERC20 for IERC20;
15 | |
16 | | DataStore public immutable dataStore;
17 | |
18 | | constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {
19 | | dataStore = _dataStore;
20 | | }
21 | |
22 | | receive() external payable {
23 | | address wnt = TokenUtils.wnt(dataStore);
24 | | if (msg.sender != wnt) {
25 | | revert Errors.InvalidNativeTokenSender(msg.sender);
26 | | }
27 | | }
28 | |
29 | | // @dev transfer tokens from this contract to a receiver
30 | | //
31 | | // @param token the token to transfer
32 | | // @param amount the amount to transfer
33 | | // @param receiver the address to transfer to
34 | * | function transferOut(
35 | | address token,
36 | | address receiver,
37 | | uint256 amount
38 | | ) external onlyController {
39 | * | _transferOut(token, receiver, amount);
40 | | }
41 | |
42 | | // @dev transfer tokens from this contract to a receiver
43 | | // handles native token transfers as well
44 | | //
45 | | // @param token the token to transfer
46 | | // @param amount the amount to transfer
47 | | // @param receiver the address to transfer to
48 | | // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token
49 | | // before transferring
50 | * | function transferOut(
51 | | address token,
52 | | address receiver,
53 | | uint256 amount,
54 | | bool shouldUnwrapNativeToken
55 | * | ) external onlyController {
56 | * | address wnt = TokenUtils.wnt(dataStore);
57 | |
58 | * | if (token == wnt && shouldUnwrapNativeToken) {
59 | | _transferOutNativeToken(token, receiver, amount);
60 | | } else {
61 | * | _transferOut(token, receiver, amount);
62 | | }
63 | | }
64 | |
65 | | // @dev transfer native tokens from this contract to a receiver
66 | | //
67 | | // @param token the token to transfer
68 | | // @param amount the amount to transfer
69 | | // @param receiver the address to transfer to
70 | | // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token
71 | | // before transferring
72 | | function transferOutNativeToken(
73 | | address receiver,
74 | | uint256 amount
75 | | ) external onlyController {
76 | | address wnt = TokenUtils.wnt(dataStore);
77 | | _transferOutNativeToken(wnt, receiver, amount);
78 | | }
79 | |
80 | | // @dev transfer tokens from this contract to a receiver
81 | | //
82 | | // @param token the token to transfer
83 | | // @param amount the amount to transfer
84 | | // @param receiver the address to transfer to
85 | * | function _transferOut(
86 | | address token,
87 | | address receiver,
88 | | uint256 amount
89 | | ) internal {
90 | * | if (receiver == address(this)) {
91 | | revert Errors.SelfTransferNotSupported(receiver);
92 | | }
93 | |
94 | * | TokenUtils.transfer(dataStore, token, receiver, amount);
95 | |
96 | * | _afterTransferOut(token);
97 | | }
98 | |
99 | | // @dev unwrap wrapped native tokens and transfer the native tokens from
100 | | // this contract to a receiver
101 | | //
102 | | // @param token the token to transfer
103 | | // @param amount the amount to transfer
104 | | // @param receiver the address to transfer to
105 | | function _transferOutNativeToken(
106 | | address token,
107 | | address receiver,
108 | | uint256 amount
109 | | ) internal {
110 | | if (receiver == address(this)) {
111 | | revert Errors.SelfTransferNotSupported(receiver);
112 | | }
113 | |
114 | | TokenUtils.withdrawAndSendNativeToken(
115 | | dataStore,
116 | | token,
117 | | receiver,
118 | | amount
119 | | );
120 | |
121 | | _afterTransferOut(token);
122 | | }
123 | |
124 | * | function _afterTransferOut(address /* token */) internal virtual {}
125 | | }
126 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/bank/StrictBank.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7 | |
8 | | import "./Bank.sol";
9 | |
10 | | // @title StrictBank
11 | | // @dev a stricter version of Bank
12 | | //
13 | | // the Bank contract does not have functions to validate the amount of tokens
14 | | // transferred in
15 | | // the Bank contract will mainly assume that safeTransferFrom calls work correctly
16 | | // and that tokens were transferred into it if there was no revert
17 | | //
18 | | // the StrictBank contract keeps track of its internal token balance
19 | | // and uses recordTransferIn to compare its change in balance and return
20 | | // the amount of tokens received
21 | * | contract StrictBank is Bank {
22 | | using SafeERC20 for IERC20;
23 | |
24 | | // used to record token balances to evaluate amounts transferred in
25 | | mapping (address => uint256) public tokenBalances;
26 | |
27 | | constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}
28 | |
29 | | // @dev records a token transfer into the contract
30 | | // @param token the token to record the transfer for
31 | | // @return the amount of tokens transferred in
32 | * | function recordTransferIn(address token) external onlyController returns (uint256) {
33 | * | return _recordTransferIn(token);
34 | | }
35 | |
36 | | // @dev this can be used to update the tokenBalances in case of token burns
37 | | // or similar balance changes
38 | | // the prevBalance is not validated to be more than the nextBalance as this
39 | | // could allow someone to block this call by transferring into the contract
40 | | // @param token the token to record the burn for
41 | | // @return the new balance
42 | * | function syncTokenBalance(address token) external onlyController returns (uint256) {
43 | * | uint256 nextBalance = IERC20(token).balanceOf(address(this));
44 | * | tokenBalances[token] = nextBalance;
45 | * | return nextBalance;
46 | | }
47 | |
48 | | // @dev records a token transfer into the contract
49 | | // @param token the token to record the transfer for
50 | | // @return the amount of tokens transferred in
51 | * | function _recordTransferIn(address token) internal returns (uint256) {
52 | * | uint256 prevBalance = tokenBalances[token];
53 | * | uint256 nextBalance = IERC20(token).balanceOf(address(this));
54 | * | tokenBalances[token] = nextBalance;
55 | |
56 | * | return nextBalance - prevBalance;
57 | | }
58 | |
59 | | // @dev update the internal balance after tokens have been transferred out
60 | | // this is called from the Bank contract
61 | | // @param token the token that was transferred out
62 | * | function _afterTransferOut(address token) internal override {
63 | * | tokenBalances[token] = IERC20(token).balanceOf(address(this));
64 | | }
65 | | }
66 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/CallbackUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/Address.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../data/Keys.sol";
9 | | import "../error/ErrorUtils.sol";
10 | |
11 | | import "./IOrderCallbackReceiver.sol";
12 | | import "./IDepositCallbackReceiver.sol";
13 | | import "./IWithdrawalCallbackReceiver.sol";
14 | | import "./IShiftCallbackReceiver.sol";
15 | | import "./IGasFeeCallbackReceiver.sol";
16 | | import "./IGlvDepositCallbackReceiver.sol";
17 | |
18 | | // @title CallbackUtils
19 | | // @dev most features require a two step process to complete
20 | | // the user first sends a request transaction, then a second transaction is sent
21 | | // by a keeper to execute the request
22 | | //
23 | | // to allow for better composability with other contracts, a callback contract
24 | | // can be specified to be called after request executions or cancellations
25 | | //
26 | | // in case it is necessary to add "before" callbacks, extra care should be taken
27 | | // to ensure that important state cannot be changed during the before callback
28 | | // for example, if an order can be cancelled in the "before" callback during
29 | | // order execution, it may lead to an order being executed even though the user
30 | | // was already refunded for its cancellation
31 | | //
32 | | // the details from callback errors are not processed to avoid cases where a malicious
33 | | // callback contract returns a very large value to cause transactions to run out of gas
34 | * | library CallbackUtils {
35 | | using Address for address;
36 | | using Deposit for Deposit.Props;
37 | | using Withdrawal for Withdrawal.Props;
38 | | using Shift for Shift.Props;
39 | | using Order for Order.Props;
40 | | using GlvDeposit for GlvDeposit.Props;
41 | |
42 | | event AfterDepositExecutionError(bytes32 key, Deposit.Props deposit);
43 | | event AfterDepositCancellationError(bytes32 key, Deposit.Props deposit);
44 | |
45 | | event AfterWithdrawalExecutionError(bytes32 key, Withdrawal.Props withdrawal);
46 | | event AfterWithdrawalCancellationError(bytes32 key, Withdrawal.Props withdrawal);
47 | |
48 | | event AfterShiftExecutionError(bytes32 key, Shift.Props shift);
49 | | event AfterShiftCancellationError(bytes32 key, Shift.Props shift);
50 | |
51 | | event AfterOrderExecutionError(bytes32 key, Order.Props order);
52 | | event AfterOrderCancellationError(bytes32 key, Order.Props order);
53 | | event AfterOrderFrozenError(bytes32 key, Order.Props order);
54 | |
55 | | event AfterGlvDepositExecutionError(bytes32 key, GlvDeposit.Props glvDeposit);
56 | | event AfterGlvDepositCancellationError(bytes32 key, GlvDeposit.Props glvDeposit);
57 | |
58 | | // @dev validate that the callbackGasLimit is less than the max specified value
59 | | // this is to prevent callback gas limits which are larger than the max gas limits per block
60 | | // as this would allow for callback contracts that can consume all gas and conditionally cause
61 | | // executions to fail
62 | | // @param dataStore DataStore
63 | | // @param callbackGasLimit the callback gas limit
64 | * | function validateCallbackGasLimit(DataStore dataStore, uint256 callbackGasLimit) internal view {
65 | * | uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT);
66 | * | if (callbackGasLimit > maxCallbackGasLimit) {
67 | | revert Errors.MaxCallbackGasLimitExceeded(callbackGasLimit, maxCallbackGasLimit);
68 | | }
69 | | }
70 | |
71 | * | function validateGasLeftForCallback(uint256 callbackGasLimit) internal view {
72 | * | uint256 gasToBeForwarded = gasleft() / 64 * 63;
73 | * | if (gasToBeForwarded < callbackGasLimit) {
74 | | revert Errors.InsufficientGasLeftForCallback(gasToBeForwarded, callbackGasLimit);
75 | | }
76 | | }
77 | |
78 | | function setSavedCallbackContract(DataStore dataStore, address account, address market, address callbackContract) internal {
79 | | dataStore.setAddress(Keys.savedCallbackContract(account, market), callbackContract);
80 | | }
81 | |
82 | * | function getSavedCallbackContract(DataStore dataStore, address account, address market) internal view returns (address) {
83 | * | return dataStore.getAddress(Keys.savedCallbackContract(account, market));
84 | | }
85 | |
86 | * | function refundExecutionFee(
87 | | DataStore dataStore,
88 | | bytes32 key,
89 | | address callbackContract,
90 | | uint256 refundFeeAmount,
91 | | EventUtils.EventLogData memory eventData
92 | * | ) internal returns (bool) {
93 | * | if (!isValidCallbackContract(callbackContract)) { return false; }
94 | |
95 | * | uint256 gasLimit = dataStore.getUint(Keys.REFUND_EXECUTION_FEE_GAS_LIMIT);
96 | |
97 | * | try IGasFeeCallbackReceiver(callbackContract).refundExecutionFee{ gas: gasLimit, value: refundFeeAmount }(
98 | * | key,
99 | * | eventData
100 | | ) {
101 | * | return true;
102 | | } catch {
103 | | return false;
104 | | }
105 | | }
106 | |
107 | | // @dev called after a deposit execution
108 | | // @param key the key of the deposit
109 | | // @param deposit the deposit that was executed
110 | * | function afterDepositExecution(
111 | | bytes32 key,
112 | | Deposit.Props memory deposit,
113 | | EventUtils.EventLogData memory eventData
114 | | ) internal {
115 | * | if (!isValidCallbackContract(deposit.callbackContract())) { return; }
116 | |
117 | * | validateGasLeftForCallback(deposit.callbackGasLimit());
118 | |
119 | * | try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositExecution{ gas: deposit.callbackGasLimit() }(
120 | * | key,
121 | * | deposit,
122 | * | eventData
123 | | ) {
124 | | } catch {
125 | | emit AfterDepositExecutionError(key, deposit);
126 | | }
127 | | }
128 | |
129 | | // @dev called after a deposit cancellation
130 | | // @param key the key of the deposit
131 | | // @param deposit the deposit that was cancelled
132 | * | function afterDepositCancellation(
133 | | bytes32 key,
134 | | Deposit.Props memory deposit,
135 | | EventUtils.EventLogData memory eventData
136 | | ) internal {
137 | * | if (!isValidCallbackContract(deposit.callbackContract())) { return; }
138 | |
139 | * | validateGasLeftForCallback(deposit.callbackGasLimit());
140 | |
141 | * | try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositCancellation{ gas: deposit.callbackGasLimit() }(
142 | * | key,
143 | * | deposit,
144 | * | eventData
145 | | ) {
146 | | } catch {
147 | | emit AfterDepositCancellationError(key, deposit);
148 | | }
149 | | }
150 | |
151 | | // @dev called after a withdrawal execution
152 | | // @param key the key of the withdrawal
153 | | // @param withdrawal the withdrawal that was executed
154 | * | function afterWithdrawalExecution(
155 | | bytes32 key,
156 | | Withdrawal.Props memory withdrawal,
157 | | EventUtils.EventLogData memory eventData
158 | | ) internal {
159 | * | if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }
160 | |
161 | | validateGasLeftForCallback(withdrawal.callbackGasLimit());
162 | |
163 | | try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalExecution{ gas: withdrawal.callbackGasLimit() }(
164 | | key,
165 | | withdrawal,
166 | | eventData
167 | | ) {
168 | | } catch {
169 | | emit AfterWithdrawalExecutionError(key, withdrawal);
170 | | }
171 | | }
172 | |
173 | | // @dev called after a withdrawal cancellation
174 | | // @param key the key of the withdrawal
175 | | // @param withdrawal the withdrawal that was cancelled
176 | * | function afterWithdrawalCancellation(
177 | | bytes32 key,
178 | | Withdrawal.Props memory withdrawal,
179 | | EventUtils.EventLogData memory eventData
180 | | ) internal {
181 | * | if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }
182 | |
183 | | validateGasLeftForCallback(withdrawal.callbackGasLimit());
184 | |
185 | | try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalCancellation{ gas: withdrawal.callbackGasLimit() }(
186 | | key,
187 | | withdrawal,
188 | | eventData
189 | | ) {
190 | | } catch {
191 | | emit AfterWithdrawalCancellationError(key, withdrawal);
192 | | }
193 | | }
194 | |
195 | | function afterShiftExecution(
196 | | bytes32 key,
197 | | Shift.Props memory shift,
198 | | EventUtils.EventLogData memory eventData
199 | | ) internal {
200 | | if (!isValidCallbackContract(shift.callbackContract())) { return; }
201 | |
202 | | validateGasLeftForCallback(shift.callbackGasLimit());
203 | |
204 | | try IShiftCallbackReceiver(shift.callbackContract()).afterShiftExecution{ gas: shift.callbackGasLimit() }(
205 | | key,
206 | | shift,
207 | | eventData
208 | | ) {
209 | | } catch {
210 | | emit AfterShiftExecutionError(key, shift);
211 | | }
212 | | }
213 | | function afterShiftCancellation(
214 | | bytes32 key,
215 | | Shift.Props memory shift,
216 | | EventUtils.EventLogData memory eventData
217 | | ) internal {
218 | | if (!isValidCallbackContract(shift.callbackContract())) { return; }
219 | |
220 | | validateGasLeftForCallback(shift.callbackGasLimit());
221 | |
222 | | try IShiftCallbackReceiver(shift.callbackContract()).afterShiftCancellation{ gas: shift.callbackGasLimit() }(
223 | | key,
224 | | shift,
225 | | eventData
226 | | ) {
227 | | } catch {
228 | | emit AfterShiftCancellationError(key, shift);
229 | | }
230 | | }
231 | |
232 | | // @dev called after an order execution
233 | | // note that the order.size, order.initialCollateralDeltaAmount and other
234 | | // properties may be updated during execution, the new values may not be
235 | | // updated in the order object for the callback
236 | | // @param key the key of the order
237 | | // @param order the order that was executed
238 | * | function afterOrderExecution(
239 | | bytes32 key,
240 | | Order.Props memory order,
241 | | EventUtils.EventLogData memory eventData
242 | | ) internal {
243 | * | if (!isValidCallbackContract(order.callbackContract())) { return; }
244 | |
245 | * | validateGasLeftForCallback(order.callbackGasLimit());
246 | |
247 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderExecution{ gas: order.callbackGasLimit() }(
248 | * | key,
249 | * | order,
250 | * | eventData
251 | | ) {
252 | | } catch {
253 | * | emit AfterOrderExecutionError(key, order);
254 | | }
255 | | }
256 | |
257 | | // @dev called after an order cancellation
258 | | // @param key the key of the order
259 | | // @param order the order that was cancelled
260 | * | function afterOrderCancellation(
261 | | bytes32 key,
262 | | Order.Props memory order,
263 | | EventUtils.EventLogData memory eventData
264 | | ) internal {
265 | * | if (!isValidCallbackContract(order.callbackContract())) { return; }
266 | |
267 | * | validateGasLeftForCallback(order.callbackGasLimit());
268 | |
269 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderCancellation{ gas: order.callbackGasLimit() }(
270 | * | key,
271 | * | order,
272 | * | eventData
273 | | ) {
274 | | } catch {
275 | | emit AfterOrderCancellationError(key, order);
276 | | }
277 | | }
278 | |
279 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info
280 | | // @param key the key of the order
281 | | // @param order the order that was frozen
282 | * | function afterOrderFrozen(
283 | | bytes32 key,
284 | | Order.Props memory order,
285 | | EventUtils.EventLogData memory eventData
286 | | ) internal {
287 | * | if (!isValidCallbackContract(order.callbackContract())) { return; }
288 | |
289 | * | validateGasLeftForCallback(order.callbackGasLimit());
290 | |
291 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderFrozen{ gas: order.callbackGasLimit() }(
292 | * | key,
293 | * | order,
294 | * | eventData
295 | | ) {
296 | | } catch {
297 | | emit AfterOrderFrozenError(key, order);
298 | | }
299 | | }
300 | |
301 | | // @dev called after a glvDeposit execution
302 | | // @param key the key of the glvDeposit
303 | | // @param glvDeposit the glvDeposit that was executed
304 | | function afterGlvDepositExecution(
305 | | bytes32 key,
306 | | GlvDeposit.Props memory glvDeposit,
307 | | EventUtils.EventLogData memory eventData
308 | | ) internal {
309 | | if (!isValidCallbackContract(glvDeposit.callbackContract())) { return; }
310 | |
311 | | try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositExecution{ gas: glvDeposit.callbackGasLimit() }(
312 | | key,
313 | | glvDeposit,
314 | | eventData
315 | | ) {
316 | | } catch {
317 | | emit AfterGlvDepositExecutionError(key, glvDeposit);
318 | | }
319 | | }
320 | |
321 | | // @dev called after a glvDeposit cancellation
322 | | // @param key the key of the glvDeposit
323 | | // @param glvDeposit the glvDeposit that was cancelled
324 | | function afterGlvDepositCancellation(
325 | | bytes32 key,
326 | | GlvDeposit.Props memory glvDeposit,
327 | | EventUtils.EventLogData memory eventData
328 | | ) internal {
329 | | if (!isValidCallbackContract(glvDeposit.callbackContract())) { return; }
330 | |
331 | | try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositCancellation{ gas: glvDeposit.callbackGasLimit() }(
332 | | key,
333 | | glvDeposit,
334 | | eventData
335 | | ) {
336 | | } catch {
337 | | emit AfterGlvDepositCancellationError(key, glvDeposit);
338 | | }
339 | | }
340 | |
341 | | // @dev validates that the given address is a contract
342 | | // @param callbackContract the contract to call
343 | * | function isValidCallbackContract(address callbackContract) internal view returns (bool) {
344 | * | if (callbackContract == address(0)) { return false; }
345 | * | if (!callbackContract.isContract()) { return false; }
346 | |
347 | * | return true;
348 | | }
349 | | }
350 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IDepositCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | | import "../deposit/Deposit.sol";
7 | |
8 | | // @title IDepositCallbackReceiver
9 | | // @dev interface for a deposit callback contract
10 | | interface IDepositCallbackReceiver {
11 | | // @dev called after a deposit execution
12 | | // @param key the key of the deposit
13 | | // @param deposit the deposit that was executed
14 | | function afterDepositExecution(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external;
15 | |
16 | | // @dev called after a deposit cancellation
17 | | // @param key the key of the deposit
18 | | // @param deposit the deposit that was cancelled
19 | | function afterDepositCancellation(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external;
20 | | }
21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IGasFeeCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | |
7 | | interface IGasFeeCallbackReceiver {
8 | | function refundExecutionFee(bytes32 key, EventUtils.EventLogData memory eventData) external payable;
9 | | }
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IGlvDepositCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | | import "../glv/GlvDeposit.sol";
7 | |
8 | | // @title IGlvDepositCallbackReceiver
9 | | // @dev interface for a glvDeposit callback contract
10 | | interface IGlvDepositCallbackReceiver {
11 | | // @dev called after a glvDeposit execution
12 | | // @param key the key of the glvDeposit
13 | | // @param glvDeposit the glvDeposit that was executed
14 | | function afterGlvDepositExecution(bytes32 key, GlvDeposit.Props memory glvDeposit, EventUtils.EventLogData memory eventData) external;
15 | |
16 | | // @dev called after a glvDeposit cancellation
17 | | // @param key the key of the glvDeposit
18 | | // @param glvDeposit the glvDeposit that was cancelled
19 | | function afterGlvDepositCancellation(bytes32 key, GlvDeposit.Props memory glvDeposit, EventUtils.EventLogData memory eventData) external;
20 | | }
21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IOrderCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | | import "../order/Order.sol";
7 | |
8 | | // @title IOrderCallbackReceiver
9 | | // @dev interface for an order callback contract
10 | | interface IOrderCallbackReceiver {
11 | | // @dev called after an order execution
12 | | // @param key the key of the order
13 | | // @param order the order that was executed
14 | | function afterOrderExecution(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
15 | |
16 | | // @dev called after an order cancellation
17 | | // @param key the key of the order
18 | | // @param order the order that was cancelled
19 | | function afterOrderCancellation(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
20 | |
21 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info
22 | | // @param key the key of the order
23 | | // @param order the order that was frozen
24 | | function afterOrderFrozen(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IShiftCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | | import "../shift/Shift.sol";
7 | |
8 | | interface IShiftCallbackReceiver {
9 | | function afterShiftExecution(bytes32 key, Shift.Props memory shift, EventUtils.EventLogData memory eventData) external;
10 | | function afterShiftCancellation(bytes32 key, Shift.Props memory shift, EventUtils.EventLogData memory eventData) external;
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IWithdrawalCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventUtils.sol";
6 | | import "../withdrawal/Withdrawal.sol";
7 | |
8 | | // @title IWithdrawalCallbackReceiver
9 | | // @dev interface for a withdrawal callback contract
10 | | interface IWithdrawalCallbackReceiver {
11 | | // @dev called after a withdrawal execution
12 | | // @param key the key of the withdrawal
13 | | // @param withdrawal the withdrawal that was executed
14 | | function afterWithdrawalExecution(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external;
15 | |
16 | | // @dev called after a withdrawal cancellation
17 | | // @param key the key of the withdrawal
18 | | // @param withdrawal the withdrawal that was cancelled
19 | | function afterWithdrawalCancellation(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external;
20 | | }
21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/chain/ArbSys.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title ArbSys
6 | | // @dev Globally available variables for Arbitrum may have both an L1 and an L2
7 | | // value, the ArbSys interface is used to retrieve the L2 value
8 | | interface ArbSys {
9 | | function arbBlockNumber() external view returns (uint256);
10 | | function arbBlockHash(uint256 blockNumber) external view returns (bytes32);
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/chain/Chain.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./ArbSys.sol";
6 | |
7 | | // @title Chain
8 | | // @dev Wrap the calls to retrieve chain variables to handle differences
9 | | // between chain implementations
10 | * | library Chain {
11 | | // if the ARBITRUM_CHAIN_ID changes, a new version of this library
12 | | // and contracts depending on it would need to be deployed
13 | * | uint256 internal constant ARBITRUM_CHAIN_ID = 42161;
14 | * | uint256 internal constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;
15 | |
16 | | ArbSys internal constant arbSys = ArbSys(address(100));
17 | |
18 | | // @dev return the current block's timestamp
19 | | // @return the current block's timestamp
20 | * | function currentTimestamp() internal view returns (uint256) {
21 | * | return block.timestamp;
22 | | }
23 | |
24 | | // @dev return the current block's number
25 | | // @return the current block's number
26 | * | function currentBlockNumber() internal view returns (uint256) {
27 | * | if (shouldUseArbSysValues()) {
28 | | return arbSys.arbBlockNumber();
29 | | }
30 | |
31 | * | return block.number;
32 | | }
33 | |
34 | | // @dev return the current block's hash
35 | | // @return the current block's hash
36 | | function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {
37 | | if (shouldUseArbSysValues()) {
38 | | return arbSys.arbBlockHash(blockNumber);
39 | | }
40 | |
41 | | return blockhash(blockNumber);
42 | | }
43 | |
44 | * | function shouldUseArbSysValues() internal view returns (bool) {
45 | * | return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;
46 | | }
47 | | }
48 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/config/Config.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../data/Keys.sol";
9 | | import "../role/RoleModule.sol";
10 | | import "../event/EventEmitter.sol";
11 | | import "../utils/BasicMulticall.sol";
12 | | import "../utils/Precision.sol";
13 | | import "../utils/Cast.sol";
14 | | import "../market/MarketUtils.sol";
15 | |
16 | | // @title Config
17 | * | contract Config is ReentrancyGuard, RoleModule, BasicMulticall {
18 | | using EventUtils for EventUtils.AddressItems;
19 | | using EventUtils for EventUtils.UintItems;
20 | | using EventUtils for EventUtils.IntItems;
21 | | using EventUtils for EventUtils.BoolItems;
22 | | using EventUtils for EventUtils.Bytes32Items;
23 | | using EventUtils for EventUtils.BytesItems;
24 | | using EventUtils for EventUtils.StringItems;
25 | |
26 | | uint256 public constant MAX_FEE_FACTOR = 5 * Precision.FLOAT_PRECISION / 100; // 5%
27 | |
28 | | DataStore public immutable dataStore;
29 | | EventEmitter public immutable eventEmitter;
30 | |
31 | | // @dev the base keys that can be set
32 | | mapping (bytes32 => bool) public allowedBaseKeys;
33 | | // @dev the limited base keys that can be set
34 | | mapping (bytes32 => bool) public allowedLimitedBaseKeys;
35 | |
36 | | constructor(
37 | | RoleStore _roleStore,
38 | | DataStore _dataStore,
39 | | EventEmitter _eventEmitter
40 | | ) RoleModule(_roleStore) {
41 | | dataStore = _dataStore;
42 | | eventEmitter = _eventEmitter;
43 | |
44 | | _initAllowedBaseKeys();
45 | | _initAllowedLimitedBaseKeys();
46 | | }
47 | |
48 | | modifier onlyKeeper() {
49 | | if (
50 | | !roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER) &&
51 | | !roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)
52 | | ) {
53 | | revert Errors.Unauthorized(msg.sender, "LIMITED / CONFIG KEEPER");
54 | | }
55 | |
56 | | _;
57 | | }
58 | |
59 | | function setFundingRate(
60 | | address market,
61 | | uint256 maxFundingFactorPerSecond
62 | | ) external onlyKeeper nonReentrant {
63 | | uint256 limit = dataStore.getUint(Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT);
64 | |
65 | | if (maxFundingFactorPerSecond > limit) {
66 | | revert Errors.MaxFundingFactorPerSecondLimitExceeded(maxFundingFactorPerSecond, limit);
67 | | }
68 | |
69 | | dataStore.setUint(Keys.maxFundingFactorPerSecondKey(market), maxFundingFactorPerSecond);
70 | |
71 | | EventUtils.EventLogData memory eventData;
72 | | eventData.addressItems.initItems(1);
73 | | eventData.addressItems.setItem(0, "market", market);
74 | | eventData.uintItems.initItems(1);
75 | | eventData.uintItems.setItem(0, "maxFundingFactorPerSecond", maxFundingFactorPerSecond);
76 | | eventEmitter.emitEventLog1(
77 | | "ConfigSetFundingRate",
78 | | Cast.toBytes32(market),
79 | | eventData
80 | | );
81 | | }
82 | |
83 | | function setPriceFeed(
84 | | address token,
85 | | address priceFeed,
86 | | uint256 priceFeedMultiplier,
87 | | uint256 priceFeedHeartbeatDuration,
88 | | uint256 stablePrice
89 | | ) external onlyConfigKeeper nonReentrant {
90 | | if (dataStore.getAddress(Keys.priceFeedKey(token)) != address(0)) {
91 | | revert Errors.PriceFeedAlreadyExistsForToken(token);
92 | | }
93 | |
94 | | dataStore.setAddress(Keys.priceFeedKey(token), priceFeed);
95 | | dataStore.setUint(Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);
96 | | dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);
97 | | dataStore.setUint(Keys.stablePriceKey(token), stablePrice);
98 | |
99 | | EventUtils.EventLogData memory eventData;
100 | | eventData.addressItems.initItems(2);
101 | | eventData.addressItems.setItem(0, "token", token);
102 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed);
103 | | eventData.uintItems.initItems(3);
104 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier);
105 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration);
106 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice);
107 | | eventEmitter.emitEventLog1(
108 | | "ConfigSetPriceFeed",
109 | | Cast.toBytes32(token),
110 | | eventData
111 | | );
112 | | }
113 | |
114 | | function setDataStream(
115 | | address token,
116 | | bytes32 feedId,
117 | | uint256 dataStreamMultiplier
118 | | ) external onlyTimelockAdmin nonReentrant {
119 | | if (dataStore.getBytes32(Keys.dataStreamIdKey(token)) != bytes32(0)) {
120 | | revert Errors.DataStreamIdAlreadyExistsForToken(token);
121 | | }
122 | |
123 | | dataStore.setBytes32(Keys.dataStreamIdKey(token), feedId);
124 | | dataStore.setUint(Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);
125 | |
126 | | EventUtils.EventLogData memory eventData;
127 | | eventData.addressItems.initItems(1);
128 | | eventData.addressItems.setItem(0, "token", token);
129 | | eventData.bytes32Items.initItems(1);
130 | | eventData.bytes32Items.setItem(0, "feedId", feedId);
131 | | eventData.uintItems.initItems(1);
132 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier);
133 | | eventEmitter.emitEventLog1(
134 | | "ConfigSetDataStream",
135 | | Cast.toBytes32(token),
136 | | eventData
137 | | );
138 | | }
139 | |
140 | | function setClaimableCollateralFactorForTime(
141 | | address market,
142 | | address token,
143 | | uint256 timeKey,
144 | | uint256 factor
145 | | ) external onlyConfigKeeper nonReentrant {
146 | | if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }
147 | |
148 | | bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey);
149 | | dataStore.setUint(key, factor);
150 | |
151 | | EventUtils.EventLogData memory eventData;
152 | |
153 | | eventData.addressItems.initItems(2);
154 | | eventData.addressItems.setItem(0, "market", market);
155 | | eventData.addressItems.setItem(1, "token", token);
156 | |
157 | | eventData.uintItems.initItems(2);
158 | | eventData.uintItems.setItem(0, "timeKey", timeKey);
159 | | eventData.uintItems.setItem(1, "factor", factor);
160 | |
161 | | eventEmitter.emitEventLog2(
162 | | "SetClaimableCollateralFactorForTime",
163 | | Cast.toBytes32(market),
164 | | Cast.toBytes32(token),
165 | | eventData
166 | | );
167 | | }
168 | |
169 | | function setClaimableCollateralFactorForAccount(
170 | | address market,
171 | | address token,
172 | | uint256 timeKey,
173 | | address account,
174 | | uint256 factor
175 | | ) external onlyConfigKeeper nonReentrant {
176 | | if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }
177 | |
178 | | bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey, account);
179 | | dataStore.setUint(key, factor);
180 | |
181 | | EventUtils.EventLogData memory eventData;
182 | |
183 | | eventData.addressItems.initItems(3);
184 | | eventData.addressItems.setItem(0, "market", market);
185 | | eventData.addressItems.setItem(1, "token", token);
186 | | eventData.addressItems.setItem(2, "account", account);
187 | |
188 | | eventData.uintItems.initItems(2);
189 | | eventData.uintItems.setItem(0, "timeKey", timeKey);
190 | | eventData.uintItems.setItem(1, "factor", factor);
191 | |
192 | | eventEmitter.emitEventLog2(
193 | | "SetClaimableCollateralFactorForAccount",
194 | | Cast.toBytes32(market),
195 | | Cast.toBytes32(token),
196 | | eventData
197 | | );
198 | | }
199 | |
200 | | function setPositionImpactDistributionRate(
201 | | address market,
202 | | uint256 minPositionImpactPoolAmount,
203 | | uint256 positionImpactPoolDistributionRate
204 | | ) external onlyConfigKeeper nonReentrant {
205 | | MarketUtils.distributePositionImpactPool(dataStore, eventEmitter, market);
206 | |
207 | | dataStore.setUint(Keys.minPositionImpactPoolAmountKey(market), minPositionImpactPoolAmount);
208 | | dataStore.setUint(Keys.positionImpactPoolDistributionRateKey(market), positionImpactPoolDistributionRate);
209 | |
210 | | dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());
211 | |
212 | | EventUtils.EventLogData memory eventData;
213 | |
214 | | eventData.addressItems.initItems(1);
215 | | eventData.addressItems.setItem(0, "market", market);
216 | |
217 | | eventData.uintItems.initItems(2);
218 | | eventData.uintItems.setItem(0, "minPositionImpactPoolAmount", minPositionImpactPoolAmount);
219 | | eventData.uintItems.setItem(1, "positionImpactPoolDistributionRate", positionImpactPoolDistributionRate);
220 | |
221 | | eventEmitter.emitEventLog1(
222 | | "SetPositionImpactPoolDistributionRate",
223 | | Cast.toBytes32(market),
224 | | eventData
225 | | );
226 | | }
227 | |
228 | | // @dev set a bool value
229 | | // @param baseKey the base key of the value to set
230 | | // @param data the additional data to be combined with the base key
231 | | // @param value the bool value
232 | | function setBool(bytes32 baseKey, bytes memory data, bool value) external onlyKeeper nonReentrant {
233 | | _validateKey(baseKey);
234 | |
235 | | bytes32 fullKey = _getFullKey(baseKey, data);
236 | |
237 | | dataStore.setBool(fullKey, value);
238 | |
239 | | EventUtils.EventLogData memory eventData;
240 | |
241 | | eventData.bytes32Items.initItems(1);
242 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey);
243 | |
244 | | eventData.bytesItems.initItems(1);
245 | | eventData.bytesItems.setItem(0, "data", data);
246 | |
247 | | eventData.boolItems.initItems(1);
248 | | eventData.boolItems.setItem(0, "value", value);
249 | |
250 | | eventEmitter.emitEventLog1(
251 | | "SetBool",
252 | | baseKey,
253 | | eventData
254 | | );
255 | | }
256 | |
257 | | // @dev set an address value
258 | | // @param baseKey the base key of the value to set
259 | | // @param data the additional data to be combined with the base key
260 | | // @param value the address value
261 | | function setAddress(bytes32 baseKey, bytes memory data, address value) external onlyKeeper nonReentrant {
262 | | _validateKey(baseKey);
263 | |
264 | | bytes32 fullKey = _getFullKey(baseKey, data);
265 | |
266 | | dataStore.setAddress(fullKey, value);
267 | |
268 | | EventUtils.EventLogData memory eventData;
269 | |
270 | | eventData.bytes32Items.initItems(1);
271 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey);
272 | |
273 | | eventData.bytesItems.initItems(1);
274 | | eventData.bytesItems.setItem(0, "data", data);
275 | |
276 | | eventData.addressItems.initItems(1);
277 | | eventData.addressItems.setItem(0, "value", value);
278 | |
279 | | eventEmitter.emitEventLog1(
280 | | "SetAddress",
281 | | baseKey,
282 | | eventData
283 | | );
284 | | }
285 | |
286 | | // @dev set a bytes32 value
287 | | // @param baseKey the base key of the value to set
288 | | // @param data the additional data to be combined with the base key
289 | | // @param value the bytes32 value
290 | | function setBytes32(bytes32 baseKey, bytes memory data, bytes32 value) external onlyKeeper nonReentrant {
291 | | _validateKey(baseKey);
292 | |
293 | | bytes32 fullKey = _getFullKey(baseKey, data);
294 | |
295 | | dataStore.setBytes32(fullKey, value);
296 | |
297 | | EventUtils.EventLogData memory eventData;
298 | |
299 | | eventData.bytes32Items.initItems(2);
300 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey);
301 | | eventData.bytes32Items.setItem(1, "value", value);
302 | |
303 | | eventData.bytesItems.initItems(1);
304 | | eventData.bytesItems.setItem(0, "data", data);
305 | |
306 | | eventEmitter.emitEventLog1(
307 | | "SetBytes32",
308 | | baseKey,
309 | | eventData
310 | | );
311 | | }
312 | |
313 | | // @dev set a uint256 value
314 | | // @param basekey the base key of the value to set
315 | | // @param data the additional data to be combined with the base key
316 | | // @param value the uint256 value
317 | | function setUint(bytes32 baseKey, bytes memory data, uint256 value) external onlyKeeper nonReentrant {
318 | | _validateKey(baseKey);
319 | |
320 | | bytes32 fullKey = _getFullKey(baseKey, data);
321 | |
322 | | _validateRange(baseKey, value);
323 | |
324 | | dataStore.setUint(fullKey, value);
325 | |
326 | | EventUtils.EventLogData memory eventData;
327 | |
328 | | eventData.bytes32Items.initItems(1);
329 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey);
330 | |
331 | | eventData.bytesItems.initItems(1);
332 | | eventData.bytesItems.setItem(0, "data", data);
333 | |
334 | | eventData.uintItems.initItems(1);
335 | | eventData.uintItems.setItem(0, "value", value);
336 | |
337 | | eventEmitter.emitEventLog1(
338 | | "SetUint",
339 | | baseKey,
340 | | eventData
341 | | );
342 | | }
343 | |
344 | | // @dev set an int256 value
345 | | // @param basekey the base key of the value to set
346 | | // @param data the additional data to be combined with the base key
347 | | // @param value the int256 value
348 | | function setInt(bytes32 baseKey, bytes memory data, int256 value) external onlyKeeper nonReentrant {
349 | | _validateKey(baseKey);
350 | |
351 | | bytes32 fullKey = _getFullKey(baseKey, data);
352 | |
353 | | dataStore.setInt(fullKey, value);
354 | |
355 | | EventUtils.EventLogData memory eventData;
356 | |
357 | | eventData.bytes32Items.initItems(1);
358 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey);
359 | |
360 | | eventData.bytesItems.initItems(1);
361 | | eventData.bytesItems.setItem(0, "data", data);
362 | |
363 | | eventData.intItems.initItems(1);
364 | | eventData.intItems.setItem(0, "value", value);
365 | |
366 | | eventEmitter.emitEventLog1(
367 | | "SetInt",
368 | | baseKey,
369 | | eventData
370 | | );
371 | | }
372 | |
373 | | function _getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {
374 | | if (data.length == 0) {
375 | | return baseKey;
376 | | }
377 | |
378 | | return keccak256(bytes.concat(baseKey, data));
379 | | }
380 | |
381 | | // @dev initialize the allowed base keys
382 | | function _initAllowedBaseKeys() internal {
383 | | allowedBaseKeys[Keys.HOLDING_ADDRESS] = true;
384 | |
385 | | allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS] = true;
386 | | allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD] = true;
387 | | allowedBaseKeys[Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION] = true;
388 | |
389 | | allowedBaseKeys[Keys.IS_MARKET_DISABLED] = true;
390 | |
391 | | allowedBaseKeys[Keys.MAX_SWAP_PATH_LENGTH] = true;
392 | | allowedBaseKeys[Keys.MAX_CALLBACK_GAS_LIMIT] = true;
393 | | allowedBaseKeys[Keys.REFUND_EXECUTION_FEE_GAS_LIMIT] = true;
394 | |
395 | | allowedBaseKeys[Keys.MIN_POSITION_SIZE_USD] = true;
396 | | allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS] = true;
397 | |
398 | | allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;
399 | | allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
400 | | allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
401 | |
402 | | allowedBaseKeys[Keys.MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT] = true;
403 | |
404 | | allowedBaseKeys[Keys.CREATE_DEPOSIT_FEATURE_DISABLED] = true;
405 | | allowedBaseKeys[Keys.CANCEL_DEPOSIT_FEATURE_DISABLED] = true;
406 | | allowedBaseKeys[Keys.EXECUTE_DEPOSIT_FEATURE_DISABLED] = true;
407 | |
408 | | allowedBaseKeys[Keys.GLV_SHIFT_FEATURE_DISABLED] = true;
409 | |
410 | | allowedBaseKeys[Keys.CREATE_WITHDRAWAL_FEATURE_DISABLED] = true;
411 | | allowedBaseKeys[Keys.CANCEL_WITHDRAWAL_FEATURE_DISABLED] = true;
412 | | allowedBaseKeys[Keys.EXECUTE_WITHDRAWAL_FEATURE_DISABLED] = true;
413 | | allowedBaseKeys[Keys.EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED] = true;
414 | |
415 | | allowedBaseKeys[Keys.CREATE_SHIFT_FEATURE_DISABLED] = true;
416 | | allowedBaseKeys[Keys.CANCEL_SHIFT_FEATURE_DISABLED] = true;
417 | | allowedBaseKeys[Keys.EXECUTE_SHIFT_FEATURE_DISABLED] = true;
418 | |
419 | | allowedBaseKeys[Keys.CREATE_ORDER_FEATURE_DISABLED] = true;
420 | | allowedBaseKeys[Keys.EXECUTE_ORDER_FEATURE_DISABLED] = true;
421 | | allowedBaseKeys[Keys.EXECUTE_ADL_FEATURE_DISABLED] = true;
422 | | allowedBaseKeys[Keys.UPDATE_ORDER_FEATURE_DISABLED] = true;
423 | | allowedBaseKeys[Keys.CANCEL_ORDER_FEATURE_DISABLED] = true;
424 | |
425 | | allowedBaseKeys[Keys.CREATE_GLV_DEPOSIT_FEATURE_DISABLED] = true;
426 | | allowedBaseKeys[Keys.CANCEL_GLV_DEPOSIT_FEATURE_DISABLED] = true;
427 | | allowedBaseKeys[Keys.EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED] = true;
428 | |
429 | | allowedBaseKeys[Keys.CLAIM_FUNDING_FEES_FEATURE_DISABLED] = true;
430 | | allowedBaseKeys[Keys.CLAIM_COLLATERAL_FEATURE_DISABLED] = true;
431 | | allowedBaseKeys[Keys.CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED] = true;
432 | | allowedBaseKeys[Keys.CLAIM_UI_FEES_FEATURE_DISABLED] = true;
433 | |
434 | | allowedBaseKeys[Keys.SUBACCOUNT_FEATURE_DISABLED] = true;
435 | |
436 | | allowedBaseKeys[Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS] = true;
437 | | allowedBaseKeys[Keys.MAX_ORACLE_PRICE_AGE] = true;
438 | | allowedBaseKeys[Keys.MAX_ORACLE_TIMESTAMP_RANGE] = true;
439 | | allowedBaseKeys[Keys.ORACLE_TIMESTAMP_ADJUSTMENT] = true;
440 | | allowedBaseKeys[Keys.ORACLE_PROVIDER_FOR_TOKEN] = true;
441 | | allowedBaseKeys[Keys.CHAINLINK_PAYMENT_TOKEN] = true;
442 | | allowedBaseKeys[Keys.SEQUENCER_GRACE_DURATION] = true;
443 | | allowedBaseKeys[Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR] = true;
444 | |
445 | | allowedBaseKeys[Keys.POSITION_FEE_RECEIVER_FACTOR] = true;
446 | | allowedBaseKeys[Keys.SWAP_FEE_RECEIVER_FACTOR] = true;
447 | | allowedBaseKeys[Keys.BORROWING_FEE_RECEIVER_FACTOR] = true;
448 | |
449 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;
450 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;
451 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;
452 | |
453 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;
454 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;
455 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;
456 | |
457 | | allowedBaseKeys[Keys.DEPOSIT_GAS_LIMIT] = true;
458 | | allowedBaseKeys[Keys.GLV_DEPOSIT_GAS_LIMIT] = true;
459 | | allowedBaseKeys[Keys.GLV_PER_MARKET_GAS_LIMIT] = true;
460 | | allowedBaseKeys[Keys.WITHDRAWAL_GAS_LIMIT] = true;
461 | | allowedBaseKeys[Keys.SHIFT_GAS_LIMIT] = true;
462 | | allowedBaseKeys[Keys.SINGLE_SWAP_GAS_LIMIT] = true;
463 | | allowedBaseKeys[Keys.INCREASE_ORDER_GAS_LIMIT] = true;
464 | | allowedBaseKeys[Keys.DECREASE_ORDER_GAS_LIMIT] = true;
465 | | allowedBaseKeys[Keys.SWAP_ORDER_GAS_LIMIT] = true;
466 | | allowedBaseKeys[Keys.TOKEN_TRANSFER_GAS_LIMIT] = true;
467 | | allowedBaseKeys[Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT] = true;
468 | |
469 | | allowedBaseKeys[Keys.REQUEST_EXPIRATION_TIME] = true;
470 | | allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR] = true;
471 | | allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER] = true;
472 | | allowedBaseKeys[Keys.MIN_COLLATERAL_USD] = true;
473 | |
474 | | allowedBaseKeys[Keys.VIRTUAL_TOKEN_ID] = true;
475 | | allowedBaseKeys[Keys.VIRTUAL_MARKET_ID] = true;
476 | | allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_SWAPS] = true;
477 | | allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_POSITIONS] = true;
478 | |
479 | | allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true;
480 | | allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true;
481 | | allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR] = true;
482 | | allowedBaseKeys[Keys.POSITION_FEE_FACTOR] = true;
483 | |
484 | | allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true;
485 | | allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true;
486 | | allowedBaseKeys[Keys.SWAP_FEE_FACTOR] = true;
487 | | allowedBaseKeys[Keys.ATOMIC_SWAP_FEE_FACTOR] = true;
488 | |
489 | | allowedBaseKeys[Keys.MAX_UI_FEE_FACTOR] = true;
490 | | allowedBaseKeys[Keys.MAX_AUTO_CANCEL_ORDERS] = true;
491 | | allowedBaseKeys[Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS] = true;
492 | |
493 | | allowedBaseKeys[Keys.ORACLE_TYPE] = true;
494 | |
495 | | allowedBaseKeys[Keys.RESERVE_FACTOR] = true;
496 | | allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true;
497 | |
498 | | allowedBaseKeys[Keys.MAX_PNL_FACTOR] = true;
499 | | allowedBaseKeys[Keys.MIN_PNL_FACTOR_AFTER_ADL] = true;
500 | |
501 | | allowedBaseKeys[Keys.FUNDING_FACTOR] = true;
502 | | allowedBaseKeys[Keys.FUNDING_EXPONENT_FACTOR] = true;
503 | | allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;
504 | | allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;
505 | | allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;
506 | | allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;
507 | | allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT] = true;
508 | | allowedBaseKeys[Keys.THRESHOLD_FOR_STABLE_FUNDING] = true;
509 | | allowedBaseKeys[Keys.THRESHOLD_FOR_DECREASE_FUNDING] = true;
510 | |
511 | | allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true;
512 | | allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true;
513 | | allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true;
514 | | allowedBaseKeys[Keys.BORROWING_FACTOR] = true;
515 | | allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true;
516 | | allowedBaseKeys[Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE] = true;
517 | |
518 | | allowedBaseKeys[Keys.PRICE_FEED_HEARTBEAT_DURATION] = true;
519 | |
520 | | allowedBaseKeys[Keys.IS_GLV_MARKET_DISABLED] = true;
521 | | allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true;
522 | | }
523 | |
524 | | function _initAllowedLimitedBaseKeys() internal {
525 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;
526 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;
527 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;
528 | |
529 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;
530 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;
531 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;
532 | |
533 | | allowedLimitedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;
534 | | allowedLimitedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
535 | | allowedLimitedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
536 | | }
537 | |
538 | | // @dev validate that the baseKey is allowed to be used
539 | | // @param baseKey the base key to validate
540 | | function _validateKey(bytes32 baseKey) internal view {
541 | | if (roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)) {
542 | | if (!allowedBaseKeys[baseKey]) {
543 | | revert Errors.InvalidBaseKey(baseKey);
544 | | }
545 | |
546 | | return;
547 | | }
548 | |
549 | | if (roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER)) {
550 | | if (!allowedLimitedBaseKeys[baseKey]) {
551 | | revert Errors.InvalidBaseKey(baseKey);
552 | | }
553 | |
554 | | return;
555 | | }
556 | |
557 | | revert Errors.InvalidBaseKey(baseKey);
558 | | }
559 | |
560 | | // @dev validate that the value is within the allowed range
561 | | // @param baseKey the base key for the value
562 | | // @param value the value to be set
563 | | function _validateRange(bytes32 baseKey, uint256 value) internal pure {
564 | | if (
565 | | baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND ||
566 | | baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT
567 | | ) {
568 | | // 0.00001% per second, ~315% per year
569 | | if (value > 100000000000000000000000) {
570 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
571 | | }
572 | | }
573 | |
574 | | if (
575 | | baseKey == Keys.BORROWING_FACTOR ||
576 | | baseKey == Keys.BASE_BORROWING_FACTOR ||
577 | | baseKey == Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR
578 | | ) {
579 | | // 0.000005% per second, ~157% per year at 100% utilization
580 | | if (value > 50000000000000000000000) {
581 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
582 | | }
583 | | }
584 | |
585 | | if (
586 | | baseKey == Keys.FUNDING_EXPONENT_FACTOR ||
587 | | baseKey == Keys.BORROWING_EXPONENT_FACTOR
588 | | ) {
589 | | // revert if value > 2
590 | | if (value > 2 * Precision.FLOAT_PRECISION) {
591 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
592 | | }
593 | | }
594 | |
595 | | if (
596 | | baseKey == Keys.POSITION_IMPACT_EXPONENT_FACTOR ||
597 | | baseKey == Keys.SWAP_IMPACT_EXPONENT_FACTOR
598 | | ) {
599 | | // revert if value > 3
600 | | if (value > 3 * Precision.FLOAT_PRECISION) {
601 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
602 | | }
603 | | }
604 | |
605 | | if (
606 | | baseKey == Keys.FUNDING_FACTOR ||
607 | | baseKey == Keys.BORROWING_FACTOR ||
608 | | baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND ||
609 | | baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND ||
610 | | baseKey == Keys.MIN_COLLATERAL_FACTOR
611 | | ) {
612 | | // revert if value > 1%
613 | | if (value > 1 * Precision.FLOAT_PRECISION / 100) {
614 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
615 | | }
616 | | }
617 | |
618 | | if (
619 | | baseKey == Keys.SWAP_FEE_FACTOR ||
620 | | baseKey == Keys.POSITION_FEE_FACTOR ||
621 | | baseKey == Keys.MAX_UI_FEE_FACTOR ||
622 | | baseKey == Keys.ATOMIC_SWAP_FEE_FACTOR
623 | | ) {
624 | | // revert if value > 5%
625 | | if (value > 5 * Precision.FLOAT_PRECISION / 100) {
626 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
627 | | }
628 | | }
629 | |
630 | | if (
631 | | baseKey == Keys.POSITION_FEE_RECEIVER_FACTOR ||
632 | | baseKey == Keys.SWAP_FEE_RECEIVER_FACTOR ||
633 | | baseKey == Keys.BORROWING_FEE_RECEIVER_FACTOR ||
634 | | baseKey == Keys.MAX_PNL_FACTOR ||
635 | | baseKey == Keys.MIN_PNL_FACTOR_AFTER_ADL ||
636 | | baseKey == Keys.OPTIMAL_USAGE_FACTOR
637 | | ) {
638 | | // revert if value > 100%
639 | | if (value > Precision.FLOAT_PRECISION) {
640 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
641 | | }
642 | | }
643 | | }
644 | | }
645 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/config/Timelock.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
6 | |
7 | | import "../role/RoleModule.sol";
8 | | import "../event/EventEmitter.sol";
9 | | import "../utils/BasicMulticall.sol";
10 | | import "../oracle/OracleStore.sol";
11 | | import "../data/DataStore.sol";
12 | | import "../data/Keys.sol";
13 | | import "../chain/Chain.sol";
14 | |
15 | | // @title Timelock
16 | * | contract Timelock is ReentrancyGuard, RoleModule, BasicMulticall {
17 | | using EventUtils for EventUtils.AddressItems;
18 | | using EventUtils for EventUtils.UintItems;
19 | | using EventUtils for EventUtils.IntItems;
20 | | using EventUtils for EventUtils.BoolItems;
21 | | using EventUtils for EventUtils.Bytes32Items;
22 | | using EventUtils for EventUtils.BytesItems;
23 | | using EventUtils for EventUtils.StringItems;
24 | |
25 | | using EnumerableSet for EnumerableSet.Bytes32Set;
26 | | using EnumerableValues for EnumerableSet.Bytes32Set;
27 | |
28 | | uint256 public constant MAX_TIMELOCK_DELAY = 5 days;
29 | |
30 | | DataStore public immutable dataStore;
31 | | EventEmitter public immutable eventEmitter;
32 | | OracleStore public immutable oracleStore;
33 | | uint256 public timelockDelay;
34 | |
35 | | mapping (bytes32 => uint256) public pendingActions;
36 | | EnumerableSet.Bytes32Set internal pendingActionsList;
37 | |
38 | | constructor(
39 | | RoleStore _roleStore,
40 | | DataStore _dataStore,
41 | | EventEmitter _eventEmitter,
42 | | OracleStore _oracleStore,
43 | | uint256 _timelockDelay
44 | | ) RoleModule(_roleStore) {
45 | | dataStore = _dataStore;
46 | | eventEmitter = _eventEmitter;
47 | | oracleStore = _oracleStore;
48 | | timelockDelay = _timelockDelay;
49 | |
50 | | _validateTimelockDelay();
51 | | }
52 | |
53 | | function getPendingActionsCount() internal view returns (uint256) {
54 | | return pendingActionsList.length();
55 | | }
56 | |
57 | | function getPendingActionsList(uint256 start, uint256 end) internal view returns (bytes32[] memory) {
58 | | return pendingActionsList.valuesAt(start, end);
59 | | }
60 | |
61 | | // @dev immediately revoke the role of an account
62 | | // @param account the account to revoke the role for
63 | | // @param roleKey the role to revoke
64 | | function revokeRole(address account, bytes32 roleKey) external onlyTimelockMultisig nonReentrant {
65 | | roleStore.revokeRole(account, roleKey);
66 | |
67 | | EventUtils.EventLogData memory eventData;
68 | | eventData.addressItems.initItems(1);
69 | | eventData.addressItems.setItem(0, "account", account);
70 | | eventData.bytes32Items.initItems(1);
71 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey);
72 | | eventEmitter.emitEventLog(
73 | | "RevokeRole",
74 | | eventData
75 | | );
76 | | }
77 | |
78 | | // @dev increase the timelock delay
79 | | // @param the new timelock delay
80 | | function increaseTimelockDelay(uint256 _timelockDelay) external onlyTimelockAdmin nonReentrant {
81 | | if (_timelockDelay <= timelockDelay) {
82 | | revert Errors.InvalidTimelockDelay(_timelockDelay);
83 | | }
84 | |
85 | | timelockDelay = _timelockDelay;
86 | |
87 | | _validateTimelockDelay();
88 | |
89 | | EventUtils.EventLogData memory eventData;
90 | | eventData.uintItems.initItems(1);
91 | | eventData.uintItems.setItem(0, "_timelockDelay", _timelockDelay);
92 | | eventEmitter.emitEventLog(
93 | | "IncreaseTimelockDelay",
94 | | eventData
95 | | );
96 | | }
97 | |
98 | | function setOracleProviderEnabled(address provider, bool value) external onlyTimelockMultisig nonReentrant {
99 | | dataStore.setBool(Keys.isOracleProviderEnabledKey(provider), value);
100 | |
101 | | EventUtils.EventLogData memory eventData;
102 | | eventData.addressItems.initItems(1);
103 | | eventData.addressItems.setItem(0, "provider", provider);
104 | | eventData.boolItems.initItems(1);
105 | | eventData.boolItems.setItem(0, "value", value);
106 | | eventEmitter.emitEventLog(
107 | | "SetOracleProviderEnabled",
108 | | eventData
109 | | );
110 | | }
111 | |
112 | | function signalSetOracleProviderEnabled(address provider, bool value) external onlyTimelockAdmin nonReentrant {
113 | | bytes32 actionKey = _setOracleProviderEnabledKey(provider, value);
114 | | _signalPendingAction(actionKey, "setOracleProviderEnabled");
115 | |
116 | | EventUtils.EventLogData memory eventData;
117 | | eventData.addressItems.initItems(1);
118 | | eventData.addressItems.setItem(0, "provider", provider);
119 | | eventData.boolItems.initItems(1);
120 | | eventData.boolItems.setItem(0, "value", value);
121 | | eventEmitter.emitEventLog(
122 | | "SignalSetOracleProviderEnabled",
123 | | eventData
124 | | );
125 | | }
126 | |
127 | | function setOracleProviderEnabledAfterSignal(address provider, bool value) external onlyTimelockAdmin nonReentrant {
128 | | bytes32 actionKey = _setOracleProviderEnabledKey(provider, value);
129 | | _validateAndClearAction(actionKey, "setOracleProviderEnabled");
130 | |
131 | | dataStore.setBool(Keys.isOracleProviderEnabledKey(provider), value);
132 | |
133 | | EventUtils.EventLogData memory eventData;
134 | | eventData.addressItems.initItems(1);
135 | | eventData.addressItems.setItem(0, "provider", provider);
136 | | eventData.boolItems.initItems(1);
137 | | eventData.boolItems.setItem(0, "value", value);
138 | | eventEmitter.emitEventLog(
139 | | "SetOracleProviderEnabled",
140 | | eventData
141 | | );
142 | | }
143 | |
144 | | function signalSetAtomicOracleProvider(address provider, bool value) external onlyTimelockAdmin nonReentrant {
145 | | bytes32 actionKey = _setAtomicOracleProviderKey(provider, value);
146 | | _signalPendingAction(actionKey, "setAtomicOracleProvider");
147 | |
148 | | EventUtils.EventLogData memory eventData;
149 | | eventData.addressItems.initItems(1);
150 | | eventData.addressItems.setItem(0, "provider", provider);
151 | | eventData.boolItems.initItems(1);
152 | | eventData.boolItems.setItem(0, "value", value);
153 | | eventEmitter.emitEventLog(
154 | | "SignalSetAtomicOracleProvider",
155 | | eventData
156 | | );
157 | | }
158 | |
159 | | function setAtomicOracleProviderAfterSignal(address provider, bool value) external onlyTimelockAdmin nonReentrant {
160 | | bytes32 actionKey = _setAtomicOracleProviderKey(provider, value);
161 | | _validateAndClearAction(actionKey, "setAtomicOracleProvider");
162 | |
163 | | dataStore.setBool(Keys.isAtomicOracleProviderKey(provider), value);
164 | |
165 | | EventUtils.EventLogData memory eventData;
166 | | eventData.addressItems.initItems(1);
167 | | eventData.addressItems.setItem(0, "provider", provider);
168 | | eventData.boolItems.initItems(1);
169 | | eventData.boolItems.setItem(0, "value", value);
170 | | eventEmitter.emitEventLog(
171 | | "SetAtomicOracleProvider",
172 | | eventData
173 | | );
174 | | }
175 | |
176 | | function signalAddOracleSigner(address account) external onlyTimelockAdmin nonReentrant {
177 | | if (account == address(0)) {
178 | | revert Errors.InvalidOracleSigner(account);
179 | | }
180 | |
181 | | bytes32 actionKey = _addOracleSignerActionKey(account);
182 | | _signalPendingAction(actionKey, "addOracleSigner");
183 | |
184 | | EventUtils.EventLogData memory eventData;
185 | | eventData.addressItems.initItems(1);
186 | | eventData.addressItems.setItem(0, "account", account);
187 | | eventEmitter.emitEventLog1(
188 | | "SignalAddOracleSigner",
189 | | actionKey,
190 | | eventData
191 | | );
192 | | }
193 | |
194 | | function addOracleSignerAfterSignal(address account) external onlyTimelockAdmin nonReentrant {
195 | | bytes32 actionKey = _addOracleSignerActionKey(account);
196 | | _validateAndClearAction(actionKey, "addOracleSigner");
197 | |
198 | | oracleStore.addSigner(account);
199 | |
200 | | EventUtils.EventLogData memory eventData;
201 | | eventData.addressItems.initItems(1);
202 | | eventData.addressItems.setItem(0, "account", account);
203 | | eventEmitter.emitEventLog1(
204 | | "AddOracleSigner",
205 | | actionKey,
206 | | eventData
207 | | );
208 | | }
209 | |
210 | | function signalRemoveOracleSigner(address account) external onlyTimelockAdmin nonReentrant {
211 | | if (account == address(0)) {
212 | | revert Errors.InvalidOracleSigner(account);
213 | | }
214 | |
215 | | bytes32 actionKey = _removeOracleSignerActionKey(account);
216 | | _signalPendingAction(actionKey, "removeOracleSigner");
217 | |
218 | | EventUtils.EventLogData memory eventData;
219 | | eventData.addressItems.initItems(1);
220 | | eventData.addressItems.setItem(0, "account", account);
221 | | eventEmitter.emitEventLog1(
222 | | "SignalRemoveOracleSigner",
223 | | actionKey,
224 | | eventData
225 | | );
226 | | }
227 | |
228 | | function removeOracleSignerAfterSignal(address account) external onlyTimelockAdmin nonReentrant {
229 | | bytes32 actionKey = _removeOracleSignerActionKey(account);
230 | | _validateAndClearAction(actionKey, "removeOracleSigner");
231 | |
232 | | oracleStore.removeSigner(account);
233 | |
234 | | EventUtils.EventLogData memory eventData;
235 | | eventData.addressItems.initItems(1);
236 | | eventData.addressItems.setItem(0, "account", account);
237 | | eventEmitter.emitEventLog1(
238 | | "RemoveOracleSigner",
239 | | actionKey,
240 | | eventData
241 | | );
242 | | }
243 | |
244 | | // @dev signal setting of the fee receiver
245 | | // @param account the new fee receiver
246 | | function signalSetFeeReceiver(address account) external onlyTimelockAdmin nonReentrant {
247 | | if (account == address(0)) {
248 | | revert Errors.InvalidFeeReceiver(account);
249 | | }
250 | |
251 | | bytes32 actionKey = _setFeeReceiverActionKey(account);
252 | | _signalPendingAction(actionKey, "setFeeReceiver");
253 | |
254 | | EventUtils.EventLogData memory eventData;
255 | | eventData.addressItems.initItems(1);
256 | | eventData.addressItems.setItem(0, "account", account);
257 | | eventEmitter.emitEventLog1(
258 | | "SignalSetFeeReceiver",
259 | | actionKey,
260 | | eventData
261 | | );
262 | | }
263 | |
264 | | // @dev set the fee receiver
265 | | // @param account the new fee receiver
266 | | function setFeeReceiverAfterSignal(address account) external onlyTimelockAdmin nonReentrant {
267 | | bytes32 actionKey = _setFeeReceiverActionKey(account);
268 | | _validateAndClearAction(actionKey, "setFeeReceiver");
269 | |
270 | | dataStore.setAddress(Keys.FEE_RECEIVER, account);
271 | |
272 | | EventUtils.EventLogData memory eventData;
273 | | eventData.addressItems.initItems(1);
274 | | eventData.addressItems.setItem(0, "account", account);
275 | | eventEmitter.emitEventLog1(
276 | | "SetFeeReceiver",
277 | | actionKey,
278 | | eventData
279 | | );
280 | | }
281 | |
282 | | // @dev signal granting of a role
283 | | // @param account the account to grant the role
284 | | // @param roleKey the role to grant
285 | | function signalGrantRole(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant {
286 | | bytes32 actionKey = _grantRoleActionKey(account, roleKey);
287 | | _signalPendingAction(actionKey, "grantRole");
288 | |
289 | | EventUtils.EventLogData memory eventData;
290 | | eventData.addressItems.initItems(1);
291 | | eventData.addressItems.setItem(0, "account", account);
292 | | eventData.bytes32Items.initItems(1);
293 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey);
294 | | eventEmitter.emitEventLog1(
295 | | "SignalGrantRole",
296 | | actionKey,
297 | | eventData
298 | | );
299 | | }
300 | |
301 | | // @dev grant a role
302 | | // @param account the account to grant the role
303 | | // @param roleKey the role to grant
304 | | function grantRoleAfterSignal(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant {
305 | | bytes32 actionKey = _grantRoleActionKey(account, roleKey);
306 | | _validateAndClearAction(actionKey, "grantRole");
307 | |
308 | | roleStore.grantRole(account, roleKey);
309 | |
310 | | EventUtils.EventLogData memory eventData;
311 | | eventData.addressItems.initItems(1);
312 | | eventData.addressItems.setItem(0, "account", account);
313 | | eventData.bytes32Items.initItems(1);
314 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey);
315 | | eventEmitter.emitEventLog1(
316 | | "GrantRole",
317 | | actionKey,
318 | | eventData
319 | | );
320 | | }
321 | |
322 | | // @dev signal revoking of a role
323 | | // @param account the account to revoke the role for
324 | | // @param roleKey the role to revoke
325 | | function signalRevokeRole(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant {
326 | | bytes32 actionKey = _revokeRoleActionKey(account, roleKey);
327 | | _signalPendingAction(actionKey, "revokeRole");
328 | |
329 | | EventUtils.EventLogData memory eventData;
330 | | eventData.addressItems.initItems(1);
331 | | eventData.addressItems.setItem(0, "account", account);
332 | | eventData.bytes32Items.initItems(1);
333 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey);
334 | | eventEmitter.emitEventLog1(
335 | | "SignalRevokeRole",
336 | | actionKey,
337 | | eventData
338 | | );
339 | | }
340 | |
341 | | // @dev revoke a role
342 | | // @param account the account to revoke the role for
343 | | // @param roleKey the role to revoke
344 | | function revokeRoleAfterSignal(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant {
345 | | bytes32 actionKey = _revokeRoleActionKey(account, roleKey);
346 | | _validateAndClearAction(actionKey, "revokeRole");
347 | |
348 | | roleStore.revokeRole(account, roleKey);
349 | |
350 | | EventUtils.EventLogData memory eventData;
351 | | eventData.addressItems.initItems(1);
352 | | eventData.addressItems.setItem(0, "account", account);
353 | | eventData.bytes32Items.initItems(1);
354 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey);
355 | | eventEmitter.emitEventLog1(
356 | | "RevokeRole",
357 | | actionKey,
358 | | eventData
359 | | );
360 | | }
361 | |
362 | | // @dev signal setting of a price feed
363 | | // @param token the token to set the price feed for
364 | | // @param priceFeed the address of the price feed
365 | | // @param priceFeedMultiplier the multiplier to apply to the price feed results
366 | | // @param stablePrice the stable price to set a range for the price feed results
367 | | function signalSetPriceFeed(
368 | | address token,
369 | | address priceFeed,
370 | | uint256 priceFeedMultiplier,
371 | | uint256 priceFeedHeartbeatDuration,
372 | | uint256 stablePrice
373 | | ) external onlyTimelockAdmin nonReentrant {
374 | | bytes32 actionKey = _setPriceFeedActionKey(
375 | | token,
376 | | priceFeed,
377 | | priceFeedMultiplier,
378 | | priceFeedHeartbeatDuration,
379 | | stablePrice
380 | | );
381 | |
382 | | _signalPendingAction(actionKey, "setPriceFeed");
383 | |
384 | | EventUtils.EventLogData memory eventData;
385 | | eventData.addressItems.initItems(2);
386 | | eventData.addressItems.setItem(0, "token", token);
387 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed);
388 | | eventData.uintItems.initItems(3);
389 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier);
390 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration);
391 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice);
392 | | eventEmitter.emitEventLog1(
393 | | "SignalSetPriceFeed",
394 | | actionKey,
395 | | eventData
396 | | );
397 | | }
398 | |
399 | | // @dev sets a price feed
400 | | // @param token the token to set the price feed for
401 | | // @param priceFeed the address of the price feed
402 | | // @param priceFeedMultiplier the multiplier to apply to the price feed results
403 | | // @param stablePrice the stable price to set a range for the price feed results
404 | | function setPriceFeedAfterSignal(
405 | | address token,
406 | | address priceFeed,
407 | | uint256 priceFeedMultiplier,
408 | | uint256 priceFeedHeartbeatDuration,
409 | | uint256 stablePrice
410 | | ) external onlyTimelockAdmin nonReentrant {
411 | | bytes32 actionKey = _setPriceFeedActionKey(
412 | | token,
413 | | priceFeed,
414 | | priceFeedMultiplier,
415 | | priceFeedHeartbeatDuration,
416 | | stablePrice
417 | | );
418 | |
419 | | _validateAndClearAction(actionKey, "setPriceFeed");
420 | |
421 | | dataStore.setAddress(Keys.priceFeedKey(token), priceFeed);
422 | | dataStore.setUint(Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);
423 | | dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);
424 | | dataStore.setUint(Keys.stablePriceKey(token), stablePrice);
425 | |
426 | | EventUtils.EventLogData memory eventData;
427 | | eventData.addressItems.initItems(2);
428 | | eventData.addressItems.setItem(0, "token", token);
429 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed);
430 | | eventData.uintItems.initItems(3);
431 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier);
432 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration);
433 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice);
434 | | eventEmitter.emitEventLog1(
435 | | "SetPriceFeed",
436 | | actionKey,
437 | | eventData
438 | | );
439 | | }
440 | |
441 | | // @dev signal setting of a data stream feed
442 | | // @param token the token to set the data stream feed for
443 | | // @param feedId the ID of the data stream feed
444 | | // @param dataStreamMultiplier the multiplier to apply to the data stream feed results
445 | | function signalSetDataStream(
446 | | address token,
447 | | bytes32 feedId,
448 | | uint256 dataStreamMultiplier
449 | | ) external onlyTimelockAdmin nonReentrant {
450 | | bytes32 actionKey = _setDataStreamActionKey(
451 | | token,
452 | | feedId,
453 | | dataStreamMultiplier
454 | | );
455 | |
456 | | _signalPendingAction(actionKey, "setDataStream");
457 | |
458 | | EventUtils.EventLogData memory eventData;
459 | | eventData.addressItems.initItems(1);
460 | | eventData.addressItems.setItem(0, "token", token);
461 | | eventData.bytes32Items.initItems(1);
462 | | eventData.bytes32Items.setItem(0, "feedId", feedId);
463 | | eventData.uintItems.initItems(1);
464 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier);
465 | | eventEmitter.emitEventLog1(
466 | | "SignalSetDataStream",
467 | | actionKey,
468 | | eventData
469 | | );
470 | | }
471 | |
472 | | // @dev sets a data stream feed
473 | | // @param token the token to set the data stream feed for
474 | | // @param feedId the ID of the data stream feed
475 | | // @param dataStreamMultiplier the multiplier to apply to the data stream feed results
476 | | function setDataStreamAfterSignal(
477 | | address token,
478 | | bytes32 feedId,
479 | | uint256 dataStreamMultiplier
480 | | ) external onlyTimelockAdmin nonReentrant {
481 | | bytes32 actionKey = _setDataStreamActionKey(
482 | | token,
483 | | feedId,
484 | | dataStreamMultiplier
485 | | );
486 | |
487 | | _validateAndClearAction(actionKey, "setDataStream");
488 | |
489 | | dataStore.setBytes32(Keys.dataStreamIdKey(token), feedId);
490 | | dataStore.setUint(Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);
491 | |
492 | | EventUtils.EventLogData memory eventData;
493 | | eventData.addressItems.initItems(1);
494 | | eventData.addressItems.setItem(0, "token", token);
495 | | eventData.bytes32Items.initItems(1);
496 | | eventData.bytes32Items.setItem(0, "feedId", feedId);
497 | | eventData.uintItems.initItems(1);
498 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier);
499 | | eventEmitter.emitEventLog1(
500 | | "SetDataStream",
501 | | actionKey,
502 | | eventData
503 | | );
504 | | }
505 | |
506 | | // @dev cancels a previously signalled pending action
507 | | // @param actionKey the key of the action to cancel
508 | | function cancelAction(bytes32 actionKey) external onlyTimelockAdmin nonReentrant {
509 | | _clearAction(actionKey, "cancelAction");
510 | | }
511 | |
512 | | // @dev signal a pending action
513 | | // @param actionKey the key of the action
514 | | // @param actionLabel a label for the action
515 | | function _signalPendingAction(bytes32 actionKey, string memory actionLabel) internal {
516 | | if (pendingActions[actionKey] != 0) {
517 | | revert Errors.ActionAlreadySignalled();
518 | | }
519 | |
520 | | pendingActions[actionKey] = Chain.currentTimestamp() + timelockDelay;
521 | | pendingActionsList.add(actionKey);
522 | |
523 | | EventUtils.EventLogData memory eventData;
524 | |
525 | | eventData.bytes32Items.initItems(1);
526 | | eventData.bytes32Items.setItem(0, "actionKey", actionKey);
527 | |
528 | | eventData.stringItems.initItems(1);
529 | | eventData.stringItems.setItem(0, "actionLabel", actionLabel);
530 | |
531 | | eventEmitter.emitEventLog1(
532 | | "SignalPendingAction",
533 | | actionKey,
534 | | eventData
535 | | );
536 | | }
537 | |
538 | | function _setOracleProviderEnabledKey(address provider, bool value) internal pure returns (bytes32) {
539 | | return keccak256(abi.encodePacked("setOracleProviderEnabled", provider, value));
540 | | }
541 | |
542 | | function _setAtomicOracleProviderKey(address provider, bool value) internal pure returns (bytes32) {
543 | | return keccak256(abi.encodePacked("setAtomicOracleProvider", provider, value));
544 | | }
545 | |
546 | | function _addOracleSignerActionKey(address account) internal pure returns (bytes32) {
547 | | return keccak256(abi.encodePacked("addOracleSigner", account));
548 | | }
549 | |
550 | | function _removeOracleSignerActionKey(address account) internal pure returns (bytes32) {
551 | | return keccak256(abi.encodePacked("removeOracleSigner", account));
552 | | }
553 | |
554 | | function _setFeeReceiverActionKey(address account) internal pure returns (bytes32) {
555 | | return keccak256(abi.encodePacked("setFeeReceiver", account));
556 | | }
557 | |
558 | | function _grantRoleActionKey(address account, bytes32 roleKey) internal pure returns (bytes32) {
559 | | return keccak256(abi.encodePacked("grantRole", account, roleKey));
560 | | }
561 | |
562 | | function _revokeRoleActionKey(address account, bytes32 roleKey) internal pure returns (bytes32) {
563 | | return keccak256(abi.encodePacked("revokeRole", account, roleKey));
564 | | }
565 | |
566 | | function _setPriceFeedActionKey(
567 | | address token,
568 | | address priceFeed,
569 | | uint256 priceFeedMultiplier,
570 | | uint256 priceFeedHeartbeatDuration,
571 | | uint256 stablePrice
572 | | ) internal pure returns (bytes32) {
573 | | return keccak256(abi.encodePacked(
574 | | "setPriceFeed",
575 | | token,
576 | | priceFeed,
577 | | priceFeedMultiplier,
578 | | priceFeedHeartbeatDuration,
579 | | stablePrice
580 | | ));
581 | | }
582 | |
583 | | function _setDataStreamActionKey(
584 | | address token,
585 | | bytes32 feedId,
586 | | uint256 dataStreamMultiplier
587 | | ) internal pure returns (bytes32) {
588 | | return keccak256(abi.encodePacked(
589 | | "setDataStream",
590 | | token,
591 | | feedId,
592 | | dataStreamMultiplier
593 | | ));
594 | | }
595 | |
596 | | // @dev validate that the action has been signalled and sufficient time has
597 | | // passed, clear the action after
598 | | function _validateAndClearAction(bytes32 actionKey, string memory actionLabel) internal {
599 | | _validateAction(actionKey);
600 | | _clearAction(actionKey, actionLabel);
601 | | }
602 | |
603 | | // @dev validate that the action has been signalled and sufficient time has passed
604 | | function _validateAction(bytes32 actionKey) internal view {
605 | | if (pendingActions[actionKey] == 0) {
606 | | revert Errors.ActionNotSignalled();
607 | | }
608 | |
609 | | if (pendingActions[actionKey] > Chain.currentTimestamp()) {
610 | | revert Errors.SignalTimeNotYetPassed(pendingActions[actionKey]);
611 | | }
612 | | }
613 | |
614 | | // @dev clear a previously signalled action
615 | | function _clearAction(bytes32 actionKey, string memory actionLabel) internal {
616 | | if (pendingActions[actionKey] == 0) {
617 | | revert Errors.ActionNotSignalled();
618 | | }
619 | | delete pendingActions[actionKey];
620 | | pendingActionsList.remove(actionKey);
621 | |
622 | | EventUtils.EventLogData memory eventData;
623 | |
624 | | eventData.bytes32Items.initItems(1);
625 | | eventData.bytes32Items.setItem(0, "actionKey", actionKey);
626 | |
627 | | eventData.stringItems.initItems(1);
628 | | eventData.stringItems.setItem(0, "actionLabel", actionLabel);
629 | |
630 | | eventEmitter.emitEventLog1(
631 | | "ClearPendingAction",
632 | | actionKey,
633 | | eventData
634 | | );
635 | | }
636 | |
637 | | function _validateTimelockDelay() internal view {
638 | | if (timelockDelay > MAX_TIMELOCK_DELAY) {
639 | | revert Errors.MaxTimelockDelayExceeded(timelockDelay);
640 | | }
641 | | }
642 | | }
643 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/data/DataStore.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../role/RoleModule.sol";
6 | | import "../utils/Calc.sol";
7 | | import "../utils/Printer.sol";
8 | |
9 | | // @title DataStore
10 | | // @dev DataStore for all general state values
11 | * | contract DataStore is RoleModule {
12 | | using SafeCast for int256;
13 | |
14 | | using EnumerableSet for EnumerableSet.Bytes32Set;
15 | | using EnumerableSet for EnumerableSet.AddressSet;
16 | | using EnumerableSet for EnumerableSet.UintSet;
17 | | using EnumerableValues for EnumerableSet.Bytes32Set;
18 | | using EnumerableValues for EnumerableSet.AddressSet;
19 | | using EnumerableValues for EnumerableSet.UintSet;
20 | |
21 | | // store for uint values
22 | | mapping(bytes32 => uint256) public uintValues;
23 | | // store for int values
24 | | mapping(bytes32 => int256) public intValues;
25 | | // store for address values
26 | | mapping(bytes32 => address) public addressValues;
27 | | // store for bool values
28 | | mapping(bytes32 => bool) public boolValues;
29 | | // store for string values
30 | | mapping(bytes32 => string) public stringValues;
31 | | // store for bytes32 values
32 | | mapping(bytes32 => bytes32) public bytes32Values;
33 | |
34 | | // store for uint[] values
35 | | mapping(bytes32 => uint256[]) public uintArrayValues;
36 | | // store for int[] values
37 | | mapping(bytes32 => int256[]) public intArrayValues;
38 | | // store for address[] values
39 | | mapping(bytes32 => address[]) public addressArrayValues;
40 | | // store for bool[] values
41 | | mapping(bytes32 => bool[]) public boolArrayValues;
42 | | // store for string[] values
43 | | mapping(bytes32 => string[]) public stringArrayValues;
44 | | // store for bytes32[] values
45 | | mapping(bytes32 => bytes32[]) public bytes32ArrayValues;
46 | |
47 | | // store for bytes32 sets
48 | | mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;
49 | | // store for address sets
50 | | mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;
51 | | // store for uint256 sets
52 | | mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;
53 | |
54 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
55 | |
56 | | // @dev get the uint value for the given key
57 | | // @param key the key of the value
58 | | // @return the uint value for the key
59 | * | function getUint(bytes32 key) external view returns (uint256) {
60 | * | return uintValues[key];
61 | | }
62 | |
63 | | // @dev set the uint value for the given key
64 | | // @param key the key of the value
65 | | // @param value the value to set
66 | | // @return the uint value for the key
67 | * | function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
68 | * | uintValues[key] = value;
69 | * | return value;
70 | | }
71 | |
72 | | // @dev delete the uint value for the given key
73 | | // @param key the key of the value
74 | * | function removeUint(bytes32 key) external onlyController {
75 | * | delete uintValues[key];
76 | | }
77 | |
78 | | // @dev add the input int value to the existing uint value
79 | | // @param key the key of the value
80 | | // @param value the input int value
81 | | // @return the new uint value
82 | * | function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {
83 | * | uint256 currValue = uintValues[key];
84 | * | if (value < 0 && (-value).toUint256() > currValue) {
85 | * | revert(errorMessage);
86 | | }
87 | * | uint256 nextUint = Calc.sumReturnUint256(currValue, value);
88 | * | uintValues[key] = nextUint;
89 | * | return nextUint;
90 | | }
91 | |
92 | | // @dev add the input uint value to the existing uint value
93 | | // @param key the key of the value
94 | | // @param value the input int value
95 | | // @return the new uint value
96 | * | function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
97 | * | uint256 currValue = uintValues[key];
98 | * | uint256 nextUint = currValue + value;
99 | * | uintValues[key] = nextUint;
100 | * | return nextUint;
101 | | }
102 | |
103 | | // @dev add the input int value to the existing uint value, prevent the uint
104 | | // value from becoming negative
105 | | // @param key the key of the value
106 | | // @param value the input int value
107 | | // @return the new uint value
108 | * | function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {
109 | * | uint256 uintValue = uintValues[key];
110 | * | if (value < 0 && (-value).toUint256() > uintValue) {
111 | | uintValues[key] = 0;
112 | | return 0;
113 | | }
114 | |
115 | * | uint256 nextUint = Calc.sumReturnUint256(uintValue, value);
116 | * | uintValues[key] = nextUint;
117 | * | return nextUint;
118 | | }
119 | |
120 | | // @dev add the input uint value to the existing uint value
121 | | // @param key the key of the value
122 | | // @param value the input uint value
123 | | // @return the new uint value
124 | * | function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
125 | * | uint256 nextUint = uintValues[key] + value;
126 | * | uintValues[key] = nextUint;
127 | * | return nextUint;
128 | | }
129 | |
130 | | // @dev subtract the input uint value from the existing uint value
131 | | // @param key the key of the value
132 | | // @param value the input uint value
133 | | // @return the new uint value
134 | * | function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
135 | * | uint256 nextUint = uintValues[key] - value;
136 | * | uintValues[key] = nextUint;
137 | * | return nextUint;
138 | | }
139 | |
140 | | // @dev get the int value for the given key
141 | | // @param key the key of the value
142 | | // @return the int value for the key
143 | | function getInt(bytes32 key) external view returns (int256) {
144 | | return intValues[key];
145 | | }
146 | |
147 | | // @dev set the int value for the given key
148 | | // @param key the key of the value
149 | | // @param value the value to set
150 | | // @return the int value for the key
151 | * | function setInt(bytes32 key, int256 value) external onlyController returns (int256) {
152 | * | intValues[key] = value;
153 | * | return value;
154 | | }
155 | |
156 | | function removeInt(bytes32 key) external onlyController {
157 | | delete intValues[key];
158 | | }
159 | |
160 | | // @dev add the input int value to the existing int value
161 | | // @param key the key of the value
162 | | // @param value the input int value
163 | | // @return the new int value
164 | | function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {
165 | | int256 nextInt = intValues[key] + value;
166 | | intValues[key] = nextInt;
167 | | return nextInt;
168 | | }
169 | |
170 | | // @dev add the input int value to the existing int value
171 | | // @param key the key of the value
172 | | // @param value the input int value
173 | | // @return the new int value
174 | | function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {
175 | | int256 nextInt = intValues[key] + value;
176 | | intValues[key] = nextInt;
177 | | return nextInt;
178 | | }
179 | |
180 | | // @dev subtract the input int value from the existing int value
181 | | // @param key the key of the value
182 | | // @param value the input int value
183 | | // @return the new int value
184 | | function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {
185 | | int256 nextInt = intValues[key] - value;
186 | | intValues[key] = nextInt;
187 | | return nextInt;
188 | | }
189 | |
190 | | // @dev get the address value for the given key
191 | | // @param key the key of the value
192 | | // @return the address value for the key
193 | * | function getAddress(bytes32 key) external view returns (address) {
194 | * | return addressValues[key];
195 | | }
196 | |
197 | | // @dev set the address value for the given key
198 | | // @param key the key of the value
199 | | // @param value the value to set
200 | | // @return the address value for the key
201 | * | function setAddress(bytes32 key, address value) external onlyController returns (address) {
202 | * | addressValues[key] = value;
203 | * | return value;
204 | | }
205 | |
206 | | // @dev delete the address value for the given key
207 | | // @param key the key of the value
208 | * | function removeAddress(bytes32 key) external onlyController {
209 | * | delete addressValues[key];
210 | | }
211 | |
212 | | // @dev get the bool value for the given key
213 | | // @param key the key of the value
214 | | // @return the bool value for the key
215 | * | function getBool(bytes32 key) external view returns (bool) {
216 | * | return boolValues[key];
217 | | }
218 | |
219 | | // @dev set the bool value for the given key
220 | | // @param key the key of the value
221 | | // @param value the value to set
222 | | // @return the bool value for the key
223 | * | function setBool(bytes32 key, bool value) external onlyController returns (bool) {
224 | * | boolValues[key] = value;
225 | * | return value;
226 | | }
227 | |
228 | | // @dev delete the bool value for the given key
229 | | // @param key the key of the value
230 | * | function removeBool(bytes32 key) external onlyController {
231 | * | delete boolValues[key];
232 | | }
233 | |
234 | | // @dev get the string value for the given key
235 | | // @param key the key of the value
236 | | // @return the string value for the key
237 | | function getString(bytes32 key) external view returns (string memory) {
238 | | return stringValues[key];
239 | | }
240 | |
241 | | // @dev set the string value for the given key
242 | | // @param key the key of the value
243 | | // @param value the value to set
244 | | // @return the string value for the key
245 | | function setString(bytes32 key, string memory value) external onlyController returns (string memory) {
246 | | stringValues[key] = value;
247 | | return value;
248 | | }
249 | |
250 | | // @dev delete the string value for the given key
251 | | // @param key the key of the value
252 | | function removeString(bytes32 key) external onlyController {
253 | | delete stringValues[key];
254 | | }
255 | |
256 | | // @dev get the bytes32 value for the given key
257 | | // @param key the key of the value
258 | | // @return the bytes32 value for the key
259 | * | function getBytes32(bytes32 key) external view returns (bytes32) {
260 | * | return bytes32Values[key];
261 | | }
262 | |
263 | | // @dev set the bytes32 value for the given key
264 | | // @param key the key of the value
265 | | // @param value the value to set
266 | | // @return the bytes32 value for the key
267 | | function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {
268 | | bytes32Values[key] = value;
269 | | return value;
270 | | }
271 | |
272 | | // @dev delete the bytes32 value for the given key
273 | | // @param key the key of the value
274 | | function removeBytes32(bytes32 key) external onlyController {
275 | | delete bytes32Values[key];
276 | | }
277 | |
278 | | // @dev get the uint array for the given key
279 | | // @param key the key of the uint array
280 | | // @return the uint array for the key
281 | | function getUintArray(bytes32 key) external view returns (uint256[] memory) {
282 | | return uintArrayValues[key];
283 | | }
284 | |
285 | | // @dev set the uint array for the given key
286 | | // @param key the key of the uint array
287 | | // @param value the value of the uint array
288 | | function setUintArray(bytes32 key, uint256[] memory value) external onlyController {
289 | | uintArrayValues[key] = value;
290 | | }
291 | |
292 | | // @dev delete the uint array for the given key
293 | | // @param key the key of the uint array
294 | | // @param value the value of the uint array
295 | | function removeUintArray(bytes32 key) external onlyController {
296 | | delete uintArrayValues[key];
297 | | }
298 | |
299 | | // @dev get the int array for the given key
300 | | // @param key the key of the int array
301 | | // @return the int array for the key
302 | | function getIntArray(bytes32 key) external view returns (int256[] memory) {
303 | | return intArrayValues[key];
304 | | }
305 | |
306 | | // @dev set the int array for the given key
307 | | // @param key the key of the int array
308 | | // @param value the value of the int array
309 | | function setIntArray(bytes32 key, int256[] memory value) external onlyController {
310 | | intArrayValues[key] = value;
311 | | }
312 | |
313 | | // @dev delete the int array for the given key
314 | | // @param key the key of the int array
315 | | // @param value the value of the int array
316 | | function removeIntArray(bytes32 key) external onlyController {
317 | | delete intArrayValues[key];
318 | | }
319 | |
320 | | // @dev get the address array for the given key
321 | | // @param key the key of the address array
322 | | // @return the address array for the key
323 | * | function getAddressArray(bytes32 key) external view returns (address[] memory) {
324 | * | return addressArrayValues[key];
325 | | }
326 | |
327 | | // @dev set the address array for the given key
328 | | // @param key the key of the address array
329 | | // @param value the value of the address array
330 | * | function setAddressArray(bytes32 key, address[] memory value) external onlyController {
331 | * | addressArrayValues[key] = value;
332 | | }
333 | |
334 | | // @dev delete the address array for the given key
335 | | // @param key the key of the address array
336 | | // @param value the value of the address array
337 | * | function removeAddressArray(bytes32 key) external onlyController {
338 | * | delete addressArrayValues[key];
339 | | }
340 | |
341 | | // @dev get the bool array for the given key
342 | | // @param key the key of the bool array
343 | | // @return the bool array for the key
344 | | function getBoolArray(bytes32 key) external view returns (bool[] memory) {
345 | | return boolArrayValues[key];
346 | | }
347 | |
348 | | // @dev set the bool array for the given key
349 | | // @param key the key of the bool array
350 | | // @param value the value of the bool array
351 | | function setBoolArray(bytes32 key, bool[] memory value) external onlyController {
352 | | boolArrayValues[key] = value;
353 | | }
354 | |
355 | | // @dev delete the bool array for the given key
356 | | // @param key the key of the bool array
357 | | // @param value the value of the bool array
358 | | function removeBoolArray(bytes32 key) external onlyController {
359 | | delete boolArrayValues[key];
360 | | }
361 | |
362 | | // @dev get the string array for the given key
363 | | // @param key the key of the string array
364 | | // @return the string array for the key
365 | | function getStringArray(bytes32 key) external view returns (string[] memory) {
366 | | return stringArrayValues[key];
367 | | }
368 | |
369 | | // @dev set the string array for the given key
370 | | // @param key the key of the string array
371 | | // @param value the value of the string array
372 | | function setStringArray(bytes32 key, string[] memory value) external onlyController {
373 | | stringArrayValues[key] = value;
374 | | }
375 | |
376 | | // @dev delete the string array for the given key
377 | | // @param key the key of the string array
378 | | // @param value the value of the string array
379 | | function removeStringArray(bytes32 key) external onlyController {
380 | | delete stringArrayValues[key];
381 | | }
382 | |
383 | | // @dev get the bytes32 array for the given key
384 | | // @param key the key of the bytes32 array
385 | | // @return the bytes32 array for the key
386 | | function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {
387 | | return bytes32ArrayValues[key];
388 | | }
389 | |
390 | | // @dev set the bytes32 array for the given key
391 | | // @param key the key of the bytes32 array
392 | | // @param value the value of the bytes32 array
393 | | function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {
394 | | bytes32ArrayValues[key] = value;
395 | | }
396 | |
397 | | // @dev delete the bytes32 array for the given key
398 | | // @param key the key of the bytes32 array
399 | | // @param value the value of the bytes32 array
400 | | function removeBytes32Array(bytes32 key) external onlyController {
401 | | delete bytes32ArrayValues[key];
402 | | }
403 | |
404 | | // @dev check whether the given value exists in the set
405 | | // @param setKey the key of the set
406 | | // @param value the value to check
407 | * | function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {
408 | * | return bytes32Sets[setKey].contains(value);
409 | | }
410 | |
411 | | // @dev get the length of the set
412 | | // @param setKey the key of the set
413 | * | function getBytes32Count(bytes32 setKey) external view returns (uint256) {
414 | * | return bytes32Sets[setKey].length();
415 | | }
416 | |
417 | | // @dev get the values of the set in the given range
418 | | // @param setKey the key of the set
419 | | // @param the start of the range, values at the start index will be returned
420 | | // in the result
421 | | // @param the end of the range, values at the end index will not be returned
422 | | // in the result
423 | * | function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {
424 | * | return bytes32Sets[setKey].valuesAt(start, end);
425 | | }
426 | |
427 | | // @dev add the given value to the set
428 | | // @param setKey the key of the set
429 | | // @param value the value to add
430 | * | function addBytes32(bytes32 setKey, bytes32 value) external onlyController {
431 | * | bytes32Sets[setKey].add(value);
432 | | }
433 | |
434 | | // @dev remove the given value from the set
435 | | // @param setKey the key of the set
436 | | // @param value the value to remove
437 | * | function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {
438 | * | bytes32Sets[setKey].remove(value);
439 | | }
440 | |
441 | | // @dev check whether the given value exists in the set
442 | | // @param setKey the key of the set
443 | | // @param value the value to check
444 | * | function containsAddress(bytes32 setKey, address value) external view returns (bool) {
445 | * | return addressSets[setKey].contains(value);
446 | | }
447 | |
448 | | // @dev get the length of the set
449 | | // @param setKey the key of the set
450 | | function getAddressCount(bytes32 setKey) external view returns (uint256) {
451 | | return addressSets[setKey].length();
452 | | }
453 | |
454 | | // @dev get the values of the set in the given range
455 | | // @param setKey the key of the set
456 | | // @param the start of the range, values at the start index will be returned
457 | | // in the result
458 | | // @param the end of the range, values at the end index will not be returned
459 | | // in the result
460 | | function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {
461 | | return addressSets[setKey].valuesAt(start, end);
462 | | }
463 | |
464 | | // @dev add the given value to the set
465 | | // @param setKey the key of the set
466 | | // @param value the value to add
467 | | function addAddress(bytes32 setKey, address value) external onlyController {
468 | | addressSets[setKey].add(value);
469 | | }
470 | |
471 | | // @dev remove the given value from the set
472 | | // @param setKey the key of the set
473 | | // @param value the value to remove
474 | | function removeAddress(bytes32 setKey, address value) external onlyController {
475 | | addressSets[setKey].remove(value);
476 | | }
477 | |
478 | | // @dev check whether the given value exists in the set
479 | | // @param setKey the key of the set
480 | | // @param value the value to check
481 | | function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {
482 | | return uintSets[setKey].contains(value);
483 | | }
484 | |
485 | | // @dev get the length of the set
486 | | // @param setKey the key of the set
487 | | function getUintCount(bytes32 setKey) external view returns (uint256) {
488 | | return uintSets[setKey].length();
489 | | }
490 | |
491 | | // @dev get the values of the set in the given range
492 | | // @param setKey the key of the set
493 | | // @param the start of the range, values at the start index will be returned
494 | | // in the result
495 | | // @param the end of the range, values at the end index will not be returned
496 | | // in the result
497 | | function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {
498 | | return uintSets[setKey].valuesAt(start, end);
499 | | }
500 | |
501 | | // @dev add the given value to the set
502 | | // @param setKey the key of the set
503 | | // @param value the value to add
504 | | function addUint(bytes32 setKey, uint256 value) external onlyController {
505 | | uintSets[setKey].add(value);
506 | | }
507 | |
508 | | // @dev remove the given value from the set
509 | | // @param setKey the key of the set
510 | | // @param value the value to remove
511 | | function removeUint(bytes32 setKey, uint256 value) external onlyController {
512 | | uintSets[setKey].remove(value);
513 | | }
514 | | }
515 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/data/Keys.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title Keys
6 | | // @dev Keys for values in the DataStore
7 | * | library Keys {
8 | | // @dev key for the address of the wrapped native token
9 | * | bytes32 internal constant WNT = keccak256(abi.encode("WNT"));
10 | | // @dev key for the nonce value used in NonceUtils
11 | * | bytes32 internal constant NONCE = keccak256(abi.encode("NONCE"));
12 | |
13 | | // @dev for sending received fees
14 | | bytes32 internal constant FEE_RECEIVER = keccak256(abi.encode("FEE_RECEIVER"));
15 | |
16 | | // @dev for holding tokens that could not be sent out
17 | | bytes32 internal constant HOLDING_ADDRESS = keccak256(abi.encode("HOLDING_ADDRESS"));
18 | |
19 | | // @dev key for the minimum gas for execution error
20 | | bytes32 internal constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS"));
21 | |
22 | | // @dev key for the minimum gas that should be forwarded for execution error handling
23 | * | bytes32 internal constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD"));
24 | |
25 | | // @dev key for the min additional gas for execution
26 | * | bytes32 internal constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode("MIN_ADDITIONAL_GAS_FOR_EXECUTION"));
27 | |
28 | | // @dev for a global reentrancy guard
29 | * | bytes32 internal constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode("REENTRANCY_GUARD_STATUS"));
30 | |
31 | | // @dev key for deposit fees
32 | * | bytes32 internal constant DEPOSIT_FEE_TYPE = keccak256(abi.encode("DEPOSIT_FEE_TYPE"));
33 | | // @dev key for withdrawal fees
34 | * | bytes32 internal constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("WITHDRAWAL_FEE_TYPE"));
35 | | // @dev key for swap fees
36 | * | bytes32 internal constant SWAP_FEE_TYPE = keccak256(abi.encode("SWAP_FEE_TYPE"));
37 | | // @dev key for position fees
38 | * | bytes32 internal constant POSITION_FEE_TYPE = keccak256(abi.encode("POSITION_FEE_TYPE"));
39 | | // @dev key for ui deposit fees
40 | * | bytes32 internal constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode("UI_DEPOSIT_FEE_TYPE"));
41 | | // @dev key for ui withdrawal fees
42 | * | bytes32 internal constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("UI_WITHDRAWAL_FEE_TYPE"));
43 | | // @dev key for ui swap fees
44 | * | bytes32 internal constant UI_SWAP_FEE_TYPE = keccak256(abi.encode("UI_SWAP_FEE_TYPE"));
45 | | // @dev key for ui position fees
46 | * | bytes32 internal constant UI_POSITION_FEE_TYPE = keccak256(abi.encode("UI_POSITION_FEE_TYPE"));
47 | |
48 | | // @dev key for ui fee factor
49 | * | bytes32 internal constant UI_FEE_FACTOR = keccak256(abi.encode("UI_FEE_FACTOR"));
50 | | // @dev key for max ui fee receiver factor
51 | * | bytes32 internal constant MAX_UI_FEE_FACTOR = keccak256(abi.encode("MAX_UI_FEE_FACTOR"));
52 | |
53 | | // @dev key for the claimable fee amount
54 | * | bytes32 internal constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_FEE_AMOUNT"));
55 | | // @dev key for the claimable ui fee amount
56 | * | bytes32 internal constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_UI_FEE_AMOUNT"));
57 | | // @dev key for the max number of auto cancel orders
58 | * | bytes32 internal constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_AUTO_CANCEL_ORDERS"));
59 | | // @dev key for the max total callback gas limit for auto cancel orders
60 | * | bytes32 internal constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS"));
61 | |
62 | | // @dev key for the market list
63 | * | bytes32 internal constant MARKET_LIST = keccak256(abi.encode("MARKET_LIST"));
64 | |
65 | | // @dev key for the fee batch list
66 | | bytes32 internal constant FEE_BATCH_LIST = keccak256(abi.encode("FEE_BATCH_LIST"));
67 | |
68 | | // @dev key for the deposit list
69 | * | bytes32 internal constant DEPOSIT_LIST = keccak256(abi.encode("DEPOSIT_LIST"));
70 | | // @dev key for the account deposit list
71 | * | bytes32 internal constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_DEPOSIT_LIST"));
72 | |
73 | | // @dev key for the withdrawal list
74 | * | bytes32 internal constant WITHDRAWAL_LIST = keccak256(abi.encode("WITHDRAWAL_LIST"));
75 | | // @dev key for the account withdrawal list
76 | * | bytes32 internal constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode("ACCOUNT_WITHDRAWAL_LIST"));
77 | |
78 | | // @dev key for the shift list
79 | | bytes32 internal constant SHIFT_LIST = keccak256(abi.encode("SHIFT_LIST"));
80 | | // @dev key for the account shift list
81 | | bytes32 internal constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode("ACCOUNT_SHIFT_LIST"));
82 | |
83 | | // @dev key for the glv list
84 | | bytes32 internal constant GLV_LIST = keccak256(abi.encode("GLV_LIST"));
85 | |
86 | | // @dev key for the glv deposit list
87 | | bytes32 internal constant GLV_DEPOSIT_LIST = keccak256(abi.encode("GLV_DEPOSIT_LIST"));
88 | | // @dev key for the account glv deposit list
89 | | bytes32 internal constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_GLV_DEPOSIT_LIST"));
90 | | // @dev key for the account glv supported market list
91 | | bytes32 internal constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode("GLV_SUPPORTED_MARKET_LIST"));
92 | |
93 | | // @dev key for the position list
94 | * | bytes32 internal constant POSITION_LIST = keccak256(abi.encode("POSITION_LIST"));
95 | | // @dev key for the account position list
96 | * | bytes32 internal constant ACCOUNT_POSITION_LIST = keccak256(abi.encode("ACCOUNT_POSITION_LIST"));
97 | |
98 | | // @dev key for the order list
99 | * | bytes32 internal constant ORDER_LIST = keccak256(abi.encode("ORDER_LIST"));
100 | | // @dev key for the account order list
101 | * | bytes32 internal constant ACCOUNT_ORDER_LIST = keccak256(abi.encode("ACCOUNT_ORDER_LIST"));
102 | |
103 | | // @dev key for the subaccount list
104 | | bytes32 internal constant SUBACCOUNT_LIST = keccak256(abi.encode("SUBACCOUNT_LIST"));
105 | |
106 | | // @dev key for the auto cancel order list
107 | * | bytes32 internal constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode("AUTO_CANCEL_ORDER_LIST"));
108 | |
109 | | // @dev key for is market disabled
110 | * | bytes32 internal constant IS_MARKET_DISABLED = keccak256(abi.encode("IS_MARKET_DISABLED"));
111 | |
112 | | // @dev key for the max swap path length allowed
113 | * | bytes32 internal constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode("MAX_SWAP_PATH_LENGTH"));
114 | | // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets
115 | * | bytes32 internal constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode("SWAP_PATH_MARKET_FLAG"));
116 | | // @dev key used to store the min market tokens for the first deposit for a market
117 | | bytes32 internal constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode("MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT"));
118 | |
119 | | // @dev key for whether the create glv deposit feature is disabled
120 | | bytes32 internal constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_GLV_DEPOSIT_FEATURE_DISABLED"));
121 | | // @dev key for whether the cancel glv deposit feature is disabled
122 | | bytes32 internal constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_GLV_DEPOSIT_FEATURE_DISABLED"));
123 | | // @dev key for whether the execute glv deposit feature is disabled
124 | | bytes32 internal constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED"));
125 | | // @dev key for whether the glv shift feature is disabled
126 | | bytes32 internal constant GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("GLV_SHIFT_FEATURE_DISABLED"));
127 | |
128 | | // @dev key for whether the create deposit feature is disabled
129 | * | bytes32 internal constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_DEPOSIT_FEATURE_DISABLED"));
130 | | // @dev key for whether the cancel deposit feature is disabled
131 | * | bytes32 internal constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_DEPOSIT_FEATURE_DISABLED"));
132 | | // @dev key for whether the execute deposit feature is disabled
133 | * | bytes32 internal constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_DEPOSIT_FEATURE_DISABLED"));
134 | |
135 | | // @dev key for whether the create withdrawal feature is disabled
136 | * | bytes32 internal constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CREATE_WITHDRAWAL_FEATURE_DISABLED"));
137 | | // @dev key for whether the cancel withdrawal feature is disabled
138 | * | bytes32 internal constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_WITHDRAWAL_FEATURE_DISABLED"));
139 | | // @dev key for whether the execute withdrawal feature is disabled
140 | * | bytes32 internal constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_WITHDRAWAL_FEATURE_DISABLED"));
141 | | // @dev key for whether the execute atomic withdrawal feature is disabled
142 | * | bytes32 internal constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED"));
143 | |
144 | | // @dev key for whether the create shift feature is disabled
145 | | bytes32 internal constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_SHIFT_FEATURE_DISABLED"));
146 | | // @dev key for whether the cancel shift feature is disabled
147 | | bytes32 internal constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_SHIFT_FEATURE_DISABLED"));
148 | | // @dev key for whether the execute shift feature is disabled
149 | | bytes32 internal constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_SHIFT_FEATURE_DISABLED"));
150 | |
151 | | // @dev key for whether the create order feature is disabled
152 | * | bytes32 internal constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CREATE_ORDER_FEATURE_DISABLED"));
153 | | // @dev key for whether the execute order feature is disabled
154 | * | bytes32 internal constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ORDER_FEATURE_DISABLED"));
155 | | // @dev key for whether the execute adl feature is disabled
156 | | // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation
157 | | // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it
158 | * | bytes32 internal constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ADL_FEATURE_DISABLED"));
159 | | // @dev key for whether the update order feature is disabled
160 | | bytes32 internal constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("UPDATE_ORDER_FEATURE_DISABLED"));
161 | | // @dev key for whether the cancel order feature is disabled
162 | * | bytes32 internal constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_ORDER_FEATURE_DISABLED"));
163 | |
164 | | // @dev key for whether the claim funding fees feature is disabled
165 | * | bytes32 internal constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_FUNDING_FEES_FEATURE_DISABLED"));
166 | | // @dev key for whether the claim collateral feature is disabled
167 | | bytes32 internal constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_COLLATERAL_FEATURE_DISABLED"));
168 | | // @dev key for whether the claim affiliate rewards feature is disabled
169 | | bytes32 internal constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED"));
170 | | // @dev key for whether the claim ui fees feature is disabled
171 | | bytes32 internal constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_UI_FEES_FEATURE_DISABLED"));
172 | | // @dev key for whether the subaccount feature is disabled
173 | | bytes32 internal constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode("SUBACCOUNT_FEATURE_DISABLED"));
174 | |
175 | | // @dev key for the minimum required oracle signers for an oracle observation
176 | | bytes32 internal constant MIN_ORACLE_SIGNERS = keccak256(abi.encode("MIN_ORACLE_SIGNERS"));
177 | | // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation
178 | | bytes32 internal constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode("MIN_ORACLE_BLOCK_CONFIRMATIONS"));
179 | | // @dev key for the maximum usable oracle price age in seconds
180 | * | bytes32 internal constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode("MAX_ORACLE_PRICE_AGE"));
181 | | // @dev key for the maximum oracle timestamp range
182 | * | bytes32 internal constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode("MAX_ORACLE_TIMESTAMP_RANGE"));
183 | | // @dev key for the maximum oracle price deviation factor from the ref price
184 | * | bytes32 internal constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode("MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR"));
185 | | // @dev key for whether an oracle provider is enabled
186 | * | bytes32 internal constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode("IS_ORACLE_PROVIDER_ENABLED"));
187 | | // @dev key for whether an oracle provider can be used for atomic actions
188 | * | bytes32 internal constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode("IS_ATOMIC_ORACLE_PROVIDER"));
189 | | // @dev key for oracle timestamp adjustment
190 | | bytes32 internal constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode("ORACLE_TIMESTAMP_ADJUSTMENT"));
191 | | // @dev key for oracle provider for token
192 | * | bytes32 internal constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode("ORACLE_PROVIDER_FOR_TOKEN"));
193 | | // @dev key for the chainlink payment token
194 | | bytes32 internal constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode("CHAINLINK_PAYMENT_TOKEN"));
195 | | // @dev key for the sequencer grace duration
196 | | bytes32 internal constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode("SEQUENCER_GRACE_DURATION"));
197 | |
198 | | // @dev key for the percentage amount of position fees to be received
199 | * | bytes32 internal constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode("POSITION_FEE_RECEIVER_FACTOR"));
200 | | // @dev key for the percentage amount of swap fees to be received
201 | * | bytes32 internal constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode("SWAP_FEE_RECEIVER_FACTOR"));
202 | | // @dev key for the percentage amount of borrowing fees to be received
203 | * | bytes32 internal constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode("BORROWING_FEE_RECEIVER_FACTOR"));
204 | |
205 | | // @dev key for the base gas limit used when estimating execution fee
206 | * | bytes32 internal constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1"));
207 | | // @dev key for the gas limit used for each oracle price when estimating execution fee
208 | * | bytes32 internal constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE"));
209 | | // @dev key for the multiplier used when estimating execution fee
210 | * | bytes32 internal constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR"));
211 | |
212 | | // @dev key for the base gas limit used when calculating execution fee
213 | * | bytes32 internal constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1"));
214 | | // @dev key for the gas limit used for each oracle price
215 | * | bytes32 internal constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("EXECUTION_GAS_FEE_PER_ORACLE_PRICE"));
216 | | // @dev key for the multiplier used when calculating execution fee
217 | * | bytes32 internal constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("EXECUTION_GAS_FEE_MULTIPLIER_FACTOR"));
218 | |
219 | | // @dev key for the estimated gas limit for deposits
220 | * | bytes32 internal constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode("DEPOSIT_GAS_LIMIT"));
221 | | // @dev key for the estimated gas limit for withdrawals
222 | * | bytes32 internal constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode("WITHDRAWAL_GAS_LIMIT"));
223 | | // @dev key for the estimated gas limit for each glv market
224 | | bytes32 internal constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode("GLV_DEPOSIT_GAS_LIMIT"));
225 | | // @dev key for the estimated gas limit for shifts
226 | | bytes32 internal constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode("GLV_PER_MARKET_GAS_LIMIT"));
227 | | // @dev key for the estimated gas limit for shifts
228 | | bytes32 internal constant SHIFT_GAS_LIMIT = keccak256(abi.encode("SHIFT_GAS_LIMIT"));
229 | | // @dev key for the estimated gas limit for single swaps
230 | * | bytes32 internal constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode("SINGLE_SWAP_GAS_LIMIT"));
231 | | // @dev key for the estimated gas limit for increase orders
232 | * | bytes32 internal constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("INCREASE_ORDER_GAS_LIMIT"));
233 | | // @dev key for the estimated gas limit for decrease orders
234 | * | bytes32 internal constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("DECREASE_ORDER_GAS_LIMIT"));
235 | | // @dev key for the estimated gas limit for swap orders
236 | * | bytes32 internal constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode("SWAP_ORDER_GAS_LIMIT"));
237 | | // @dev key for the amount of gas to forward for token transfers
238 | * | bytes32 internal constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("TOKEN_TRANSFER_GAS_LIMIT"));
239 | | // @dev key for the amount of gas to forward for native token transfers
240 | | bytes32 internal constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("NATIVE_TOKEN_TRANSFER_GAS_LIMIT"));
241 | | // @dev key for the request expiration time, after which the request will be considered expired
242 | * | bytes32 internal constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode("REQUEST_EXPIRATION_TIME"));
243 | |
244 | * | bytes32 internal constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode("MAX_CALLBACK_GAS_LIMIT"));
245 | * | bytes32 internal constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode("REFUND_EXECUTION_FEE_GAS_LIMIT"));
246 | * | bytes32 internal constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode("SAVED_CALLBACK_CONTRACT"));
247 | |
248 | | // @dev key for the min collateral factor
249 | * | bytes32 internal constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode("MIN_COLLATERAL_FACTOR"));
250 | | // @dev key for the min collateral factor for open interest multiplier
251 | * | bytes32 internal constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode("MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER"));
252 | | // @dev key for the min allowed collateral in USD
253 | * | bytes32 internal constant MIN_COLLATERAL_USD = keccak256(abi.encode("MIN_COLLATERAL_USD"));
254 | | // @dev key for the min allowed position size in USD
255 | * | bytes32 internal constant MIN_POSITION_SIZE_USD = keccak256(abi.encode("MIN_POSITION_SIZE_USD"));
256 | |
257 | | // @dev key for the virtual id of tokens
258 | * | bytes32 internal constant VIRTUAL_TOKEN_ID = keccak256(abi.encode("VIRTUAL_TOKEN_ID"));
259 | | // @dev key for the virtual id of markets
260 | * | bytes32 internal constant VIRTUAL_MARKET_ID = keccak256(abi.encode("VIRTUAL_MARKET_ID"));
261 | | // @dev key for the virtual inventory for swaps
262 | | bytes32 internal constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_SWAPS"));
263 | | // @dev key for the virtual inventory for positions
264 | | bytes32 internal constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_POSITIONS"));
265 | |
266 | | // @dev key for the position impact factor
267 | * | bytes32 internal constant POSITION_IMPACT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_FACTOR"));
268 | | // @dev key for the position impact exponent factor
269 | * | bytes32 internal constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_EXPONENT_FACTOR"));
270 | | // @dev key for the max decrease position impact factor
271 | * | bytes32 internal constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR"));
272 | | // @dev key for the max position impact factor for liquidations
273 | | bytes32 internal constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS"));
274 | | // @dev key for the position fee factor
275 | * | bytes32 internal constant POSITION_FEE_FACTOR = keccak256(abi.encode("POSITION_FEE_FACTOR"));
276 | | // @dev key for the swap impact factor
277 | * | bytes32 internal constant SWAP_IMPACT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_FACTOR"));
278 | | // @dev key for the swap impact exponent factor
279 | * | bytes32 internal constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_EXPONENT_FACTOR"));
280 | | // @dev key for the swap fee factor
281 | * | bytes32 internal constant SWAP_FEE_FACTOR = keccak256(abi.encode("SWAP_FEE_FACTOR"));
282 | | // @dev key for the atomic swap fee factor
283 | * | bytes32 internal constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode("ATOMIC_SWAP_FEE_FACTOR"));
284 | | // @dev key for the oracle type
285 | | bytes32 internal constant ORACLE_TYPE = keccak256(abi.encode("ORACLE_TYPE"));
286 | | // @dev key for open interest
287 | * | bytes32 internal constant OPEN_INTEREST = keccak256(abi.encode("OPEN_INTEREST"));
288 | | // @dev key for open interest in tokens
289 | * | bytes32 internal constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode("OPEN_INTEREST_IN_TOKENS"));
290 | | // @dev key for collateral sum for a market
291 | * | bytes32 internal constant COLLATERAL_SUM = keccak256(abi.encode("COLLATERAL_SUM"));
292 | | // @dev key for pool amount
293 | * | bytes32 internal constant POOL_AMOUNT = keccak256(abi.encode("POOL_AMOUNT"));
294 | | // @dev key for max pool amount
295 | * | bytes32 internal constant MAX_POOL_AMOUNT = keccak256(abi.encode("MAX_POOL_AMOUNT"));
296 | | // @dev key for max pool usd for deposit
297 | * | bytes32 internal constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode("MAX_POOL_USD_FOR_DEPOSIT"));
298 | | // @dev key for max open interest
299 | * | bytes32 internal constant MAX_OPEN_INTEREST = keccak256(abi.encode("MAX_OPEN_INTEREST"));
300 | | // @dev key for position impact pool amount
301 | * | bytes32 internal constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("POSITION_IMPACT_POOL_AMOUNT"));
302 | | // @dev key for min position impact pool amount
303 | | bytes32 internal constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("MIN_POSITION_IMPACT_POOL_AMOUNT"));
304 | | // @dev key for position impact pool distribution rate
305 | * | bytes32 internal constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTION_RATE"));
306 | | // @dev key for position impact pool distributed at
307 | * | bytes32 internal constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTED_AT"));
308 | | // @dev key for swap impact pool amount
309 | * | bytes32 internal constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode("SWAP_IMPACT_POOL_AMOUNT"));
310 | | // @dev key for price feed
311 | | bytes32 internal constant PRICE_FEED = keccak256(abi.encode("PRICE_FEED"));
312 | | // @dev key for price feed multiplier
313 | | bytes32 internal constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode("PRICE_FEED_MULTIPLIER"));
314 | | // @dev key for price feed heartbeat
315 | | bytes32 internal constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode("PRICE_FEED_HEARTBEAT_DURATION"));
316 | | // @dev key for data stream feed id
317 | | bytes32 internal constant DATA_STREAM_ID = keccak256(abi.encode("DATA_STREAM_ID"));
318 | | // @dev key for data stream feed multipler
319 | | bytes32 internal constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode("DATA_STREAM_MULTIPLIER"));
320 | | // @dev key for stable price
321 | | bytes32 internal constant STABLE_PRICE = keccak256(abi.encode("STABLE_PRICE"));
322 | | // @dev key for reserve factor
323 | * | bytes32 internal constant RESERVE_FACTOR = keccak256(abi.encode("RESERVE_FACTOR"));
324 | | // @dev key for open interest reserve factor
325 | * | bytes32 internal constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode("OPEN_INTEREST_RESERVE_FACTOR"));
326 | | // @dev key for max pnl factor
327 | * | bytes32 internal constant MAX_PNL_FACTOR = keccak256(abi.encode("MAX_PNL_FACTOR"));
328 | | // @dev key for max pnl factor
329 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS"));
330 | | // @dev key for max pnl factor for adl
331 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_ADL"));
332 | | // @dev key for min pnl factor for adl
333 | * | bytes32 internal constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode("MIN_PNL_FACTOR_AFTER_ADL"));
334 | | // @dev key for max pnl factor
335 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_DEPOSITS"));
336 | | // @dev key for max pnl factor for withdrawals
337 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_WITHDRAWALS"));
338 | | // @dev key for latest ADL at
339 | * | bytes32 internal constant LATEST_ADL_AT = keccak256(abi.encode("LATEST_ADL_AT"));
340 | | // @dev key for whether ADL is enabled
341 | * | bytes32 internal constant IS_ADL_ENABLED = keccak256(abi.encode("IS_ADL_ENABLED"));
342 | | // @dev key for funding factor
343 | * | bytes32 internal constant FUNDING_FACTOR = keccak256(abi.encode("FUNDING_FACTOR"));
344 | | // @dev key for funding exponent factor
345 | * | bytes32 internal constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode("FUNDING_EXPONENT_FACTOR"));
346 | | // @dev key for saved funding factor
347 | * | bytes32 internal constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("SAVED_FUNDING_FACTOR_PER_SECOND"));
348 | | // @dev key for funding increase factor
349 | * | bytes32 internal constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_INCREASE_FACTOR_PER_SECOND"));
350 | | // @dev key for funding decrease factor
351 | | bytes32 internal constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_DECREASE_FACTOR_PER_SECOND"));
352 | | // @dev key for min funding factor
353 | | bytes32 internal constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MIN_FUNDING_FACTOR_PER_SECOND"));
354 | | // @dev key for max funding factor
355 | * | bytes32 internal constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MAX_FUNDING_FACTOR_PER_SECOND"));
356 | | // @dev key for max funding factor limit
357 | | bytes32 internal constant MAX_FUNDING_FACTOR_PER_SECOND_LIMIT = keccak256(abi.encode("MAX_FUNDING_FACTOR_PER_SECOND_LIMIT"));
358 | | // @dev key for threshold for stable funding
359 | | bytes32 internal constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_STABLE_FUNDING"));
360 | | // @dev key for threshold for decrease funding
361 | | bytes32 internal constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_DECREASE_FUNDING"));
362 | | // @dev key for funding fee amount per size
363 | * | bytes32 internal constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE"));
364 | | // @dev key for claimable funding amount per size
365 | * | bytes32 internal constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
366 | | // @dev key for when funding was last updated at
367 | * | bytes32 internal constant FUNDING_UPDATED_AT = keccak256(abi.encode("FUNDING_UPDATED_AT"));
368 | | // @dev key for claimable funding amount
369 | * | bytes32 internal constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT"));
370 | | // @dev key for claimable collateral amount
371 | * | bytes32 internal constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMABLE_COLLATERAL_AMOUNT"));
372 | | // @dev key for claimable collateral factor
373 | | bytes32 internal constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_FACTOR"));
374 | | // @dev key for claimable collateral time divisor
375 | | bytes32 internal constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_TIME_DIVISOR"));
376 | | // @dev key for claimed collateral amount
377 | | bytes32 internal constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMED_COLLATERAL_AMOUNT"));
378 | | // @dev key for optimal usage factor
379 | * | bytes32 internal constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode("OPTIMAL_USAGE_FACTOR"));
380 | | // @dev key for base borrowing factor
381 | | bytes32 internal constant BASE_BORROWING_FACTOR = keccak256(abi.encode("BASE_BORROWING_FACTOR"));
382 | | // @dev key for above optimal usage borrowing factor
383 | | bytes32 internal constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode("ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR"));
384 | | // @dev key for borrowing factor
385 | * | bytes32 internal constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR"));
386 | | // @dev key for borrowing factor
387 | * | bytes32 internal constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode("BORROWING_EXPONENT_FACTOR"));
388 | | // @dev key for skipping the borrowing factor for the smaller side
389 | * | bytes32 internal constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode("SKIP_BORROWING_FEE_FOR_SMALLER_SIDE"));
390 | | // @dev key for cumulative borrowing factor
391 | * | bytes32 internal constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR"));
392 | | // @dev key for when the cumulative borrowing factor was last updated at
393 | * | bytes32 internal constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR_UPDATED_AT"));
394 | | // @dev key for total borrowing amount
395 | * | bytes32 internal constant TOTAL_BORROWING = keccak256(abi.encode("TOTAL_BORROWING"));
396 | | // @dev key for affiliate reward
397 | * | bytes32 internal constant AFFILIATE_REWARD = keccak256(abi.encode("AFFILIATE_REWARD"));
398 | | // @dev key for max allowed subaccount action count
399 | | bytes32 internal constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT"));
400 | | // @dev key for subaccount action count
401 | | bytes32 internal constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("SUBACCOUNT_ACTION_COUNT"));
402 | | // @dev key for subaccount auto top up amount
403 | | bytes32 internal constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode("SUBACCOUNT_AUTO_TOP_UP_AMOUNT"));
404 | | // @dev key for subaccount order action
405 | | bytes32 internal constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode("SUBACCOUNT_ORDER_ACTION"));
406 | | // @dev key for fee distributor swap order token index
407 | | bytes32 internal constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX"));
408 | | // @dev key for fee distributor swap fee batch
409 | | bytes32 internal constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_FEE_BATCH"));
410 | |
411 | | // @dev key for the glv pending shift
412 | | bytes32 internal constant GLV_PENDING_SHIFT = keccak256(abi.encode("GLV_PENDING_SHIFT"));
413 | | bytes32 internal constant GLV_PENDING_SHIFT_BACKREF = keccak256(abi.encode("GLV_PENDING_SHIFT_BACKREF"));
414 | | // @dev key for the max market token balance usd for glv
415 | | bytes32 internal constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode("GLV_MAX_MARKET_TOKEN_BALANCE_USD"));
416 | | // @dev key for is glv market disabled
417 | | bytes32 internal constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode("IS_GLV_MARKET_DISABLED"));
418 | |
419 | | // @dev constant for user initiated cancel reason
420 | | string internal constant USER_INITIATED_CANCEL = "USER_INITIATED_CANCEL";
421 | |
422 | | // @dev key for the account deposit list
423 | | // @param account the account for the list
424 | * | function accountDepositListKey(address account) internal pure returns (bytes32) {
425 | * | return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));
426 | | }
427 | |
428 | | // @dev key for the account withdrawal list
429 | | // @param account the account for the list
430 | * | function accountWithdrawalListKey(address account) internal pure returns (bytes32) {
431 | * | return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));
432 | | }
433 | |
434 | | // @dev key for the account shift list
435 | | // @param account the account for the list
436 | | function accountShiftListKey(address account) internal pure returns (bytes32) {
437 | | return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));
438 | | }
439 | |
440 | | // @dev key for the account glv deposit list
441 | | // @param account the account for the list
442 | | function accountGlvDepositListKey(address account) internal pure returns (bytes32) {
443 | | return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));
444 | | }
445 | |
446 | | // @dev key for the glv supported market list
447 | | // @param glv the glv for the supported market list
448 | | function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {
449 | | return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));
450 | | }
451 | |
452 | | // @dev key for the account position list
453 | | // @param account the account for the list
454 | * | function accountPositionListKey(address account) internal pure returns (bytes32) {
455 | * | return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));
456 | | }
457 | |
458 | | // @dev key for the account order list
459 | | // @param account the account for the list
460 | * | function accountOrderListKey(address account) internal pure returns (bytes32) {
461 | * | return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));
462 | | }
463 | |
464 | | // @dev key for the subaccount list
465 | | // @param account the account for the list
466 | | function subaccountListKey(address account) internal pure returns (bytes32) {
467 | | return keccak256(abi.encode(SUBACCOUNT_LIST, account));
468 | | }
469 | |
470 | | // @dev key for the auto cancel order list
471 | | // @param position key the position key for the list
472 | * | function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {
473 | * | return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));
474 | | }
475 | |
476 | | // @dev key for the claimable fee amount
477 | | // @param market the market for the fee
478 | | // @param token the token for the fee
479 | * | function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {
480 | * | return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));
481 | | }
482 | |
483 | | // @dev key for the claimable ui fee amount
484 | | // @param market the market for the fee
485 | | // @param token the token for the fee
486 | | // @param account the account that can claim the ui fee
487 | * | function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {
488 | * | return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));
489 | | }
490 | |
491 | | // @dev key for the claimable ui fee amount for account
492 | | // @param market the market for the fee
493 | | // @param token the token for the fee
494 | | // @param account the account that can claim the ui fee
495 | | function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {
496 | | return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));
497 | | }
498 | |
499 | | // @dev key for deposit gas limit
500 | | // @param singleToken whether a single token or pair tokens are being deposited
501 | | // @return key for deposit gas limit
502 | * | function depositGasLimitKey(bool singleToken) internal pure returns (bytes32) {
503 | * | return keccak256(abi.encode(
504 | | DEPOSIT_GAS_LIMIT,
505 | * | singleToken
506 | | ));
507 | | }
508 | |
509 | | // @dev key for withdrawal gas limit
510 | | // @return key for withdrawal gas limit
511 | * | function withdrawalGasLimitKey() internal pure returns (bytes32) {
512 | * | return WITHDRAWAL_GAS_LIMIT;
513 | | }
514 | |
515 | | // @dev key for shift gas limit
516 | | // @return key for shift gas limit
517 | | function shiftGasLimitKey() internal pure returns (bytes32) {
518 | | return SHIFT_GAS_LIMIT;
519 | | }
520 | |
521 | | function glvDepositGasLimitKey() internal pure returns (bytes32) {
522 | | return GLV_DEPOSIT_GAS_LIMIT;
523 | | }
524 | |
525 | | function glvPerMarketGasLimitKey() internal pure returns (bytes32) {
526 | | return GLV_PER_MARKET_GAS_LIMIT;
527 | | }
528 | |
529 | | // @dev key for single swap gas limit
530 | | // @return key for single swap gas limit
531 | * | function singleSwapGasLimitKey() internal pure returns (bytes32) {
532 | * | return SINGLE_SWAP_GAS_LIMIT;
533 | | }
534 | |
535 | | // @dev key for increase order gas limit
536 | | // @return key for increase order gas limit
537 | * | function increaseOrderGasLimitKey() internal pure returns (bytes32) {
538 | * | return INCREASE_ORDER_GAS_LIMIT;
539 | | }
540 | |
541 | | // @dev key for decrease order gas limit
542 | | // @return key for decrease order gas limit
543 | * | function decreaseOrderGasLimitKey() internal pure returns (bytes32) {
544 | * | return DECREASE_ORDER_GAS_LIMIT;
545 | | }
546 | |
547 | | // @dev key for swap order gas limit
548 | | // @return key for swap order gas limit
549 | * | function swapOrderGasLimitKey() internal pure returns (bytes32) {
550 | * | return SWAP_ORDER_GAS_LIMIT;
551 | | }
552 | |
553 | * | function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {
554 | * | return keccak256(abi.encode(
555 | | SWAP_PATH_MARKET_FLAG,
556 | * | market
557 | | ));
558 | | }
559 | |
560 | | // @dev key for whether create glv deposit is disabled
561 | | // @param the create deposit module
562 | | // @return key for whether create deposit is disabled
563 | | function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
564 | | return keccak256(abi.encode(
565 | | CREATE_GLV_DEPOSIT_FEATURE_DISABLED,
566 | | module
567 | | ));
568 | | }
569 | |
570 | | // @dev key for whether cancel glv deposit is disabled
571 | | // @param the cancel deposit module
572 | | // @return key for whether cancel deposit is disabled
573 | | function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
574 | | return keccak256(abi.encode(
575 | | CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,
576 | | module
577 | | ));
578 | | }
579 | |
580 | | // @dev key for whether execute glv deposit is disabled
581 | | // @param the execute deposit module
582 | | // @return key for whether execute deposit is disabled
583 | | function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
584 | | return keccak256(abi.encode(
585 | | EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,
586 | | module
587 | | ));
588 | | }
589 | |
590 | | // @dev key for whether shift deposit is disabled
591 | | // @param the execute deposit module
592 | | // @return key for whether execute deposit is disabled
593 | | function glvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
594 | | return keccak256(abi.encode(
595 | | GLV_SHIFT_FEATURE_DISABLED,
596 | | module
597 | | ));
598 | | }
599 | |
600 | |
601 | | // @dev key for whether create deposit is disabled
602 | | // @param the create deposit module
603 | | // @return key for whether create deposit is disabled
604 | * | function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
605 | * | return keccak256(abi.encode(
606 | | CREATE_DEPOSIT_FEATURE_DISABLED,
607 | * | module
608 | | ));
609 | | }
610 | |
611 | | // @dev key for whether cancel deposit is disabled
612 | | // @param the cancel deposit module
613 | | // @return key for whether cancel deposit is disabled
614 | * | function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
615 | * | return keccak256(abi.encode(
616 | | CANCEL_DEPOSIT_FEATURE_DISABLED,
617 | * | module
618 | | ));
619 | | }
620 | |
621 | | // @dev key for whether execute deposit is disabled
622 | | // @param the execute deposit module
623 | | // @return key for whether execute deposit is disabled
624 | * | function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
625 | * | return keccak256(abi.encode(
626 | | EXECUTE_DEPOSIT_FEATURE_DISABLED,
627 | * | module
628 | | ));
629 | | }
630 | |
631 | | // @dev key for whether create withdrawal is disabled
632 | | // @param the create withdrawal module
633 | | // @return key for whether create withdrawal is disabled
634 | * | function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
635 | * | return keccak256(abi.encode(
636 | | CREATE_WITHDRAWAL_FEATURE_DISABLED,
637 | * | module
638 | | ));
639 | | }
640 | |
641 | | // @dev key for whether cancel withdrawal is disabled
642 | | // @param the cancel withdrawal module
643 | | // @return key for whether cancel withdrawal is disabled
644 | * | function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
645 | * | return keccak256(abi.encode(
646 | | CANCEL_WITHDRAWAL_FEATURE_DISABLED,
647 | * | module
648 | | ));
649 | | }
650 | |
651 | | // @dev key for whether execute withdrawal is disabled
652 | | // @param the execute withdrawal module
653 | | // @return key for whether execute withdrawal is disabled
654 | * | function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
655 | * | return keccak256(abi.encode(
656 | | EXECUTE_WITHDRAWAL_FEATURE_DISABLED,
657 | * | module
658 | | ));
659 | | }
660 | |
661 | | // @dev key for whether execute atomic withdrawal is disabled
662 | | // @param the execute atomic withdrawal module
663 | | // @return key for whether execute atomic withdrawal is disabled
664 | * | function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
665 | * | return keccak256(abi.encode(
666 | | EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,
667 | * | module
668 | | ));
669 | | }
670 | |
671 | | // @dev key for whether create shift is disabled
672 | | // @param the create shift module
673 | | // @return key for whether create shift is disabled
674 | | function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
675 | | return keccak256(abi.encode(
676 | | CREATE_SHIFT_FEATURE_DISABLED,
677 | | module
678 | | ));
679 | | }
680 | |
681 | | // @dev key for whether cancel shift is disabled
682 | | // @param the cancel shift module
683 | | // @return key for whether cancel shift is disabled
684 | | function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
685 | | return keccak256(abi.encode(
686 | | CANCEL_SHIFT_FEATURE_DISABLED,
687 | | module
688 | | ));
689 | | }
690 | |
691 | | // @dev key for whether execute shift is disabled
692 | | // @param the execute shift module
693 | | // @return key for whether execute shift is disabled
694 | | function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
695 | | return keccak256(abi.encode(
696 | | EXECUTE_SHIFT_FEATURE_DISABLED,
697 | | module
698 | | ));
699 | | }
700 | |
701 | | // @dev key for whether create order is disabled
702 | | // @param the create order module
703 | | // @return key for whether create order is disabled
704 | * | function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
705 | * | return keccak256(abi.encode(
706 | | CREATE_ORDER_FEATURE_DISABLED,
707 | * | module,
708 | * | orderType
709 | | ));
710 | | }
711 | |
712 | | // @dev key for whether execute order is disabled
713 | | // @param the execute order module
714 | | // @return key for whether execute order is disabled
715 | * | function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
716 | * | return keccak256(abi.encode(
717 | | EXECUTE_ORDER_FEATURE_DISABLED,
718 | * | module,
719 | * | orderType
720 | | ));
721 | | }
722 | |
723 | | // @dev key for whether execute adl is disabled
724 | | // @param the execute adl module
725 | | // @return key for whether execute adl is disabled
726 | * | function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
727 | * | return keccak256(abi.encode(
728 | | EXECUTE_ADL_FEATURE_DISABLED,
729 | * | module,
730 | * | orderType
731 | | ));
732 | | }
733 | |
734 | | // @dev key for whether update order is disabled
735 | | // @param the update order module
736 | | // @return key for whether update order is disabled
737 | | function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
738 | | return keccak256(abi.encode(
739 | | UPDATE_ORDER_FEATURE_DISABLED,
740 | | module,
741 | | orderType
742 | | ));
743 | | }
744 | |
745 | | // @dev key for whether cancel order is disabled
746 | | // @param the cancel order module
747 | | // @return key for whether cancel order is disabled
748 | * | function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
749 | * | return keccak256(abi.encode(
750 | | CANCEL_ORDER_FEATURE_DISABLED,
751 | * | module,
752 | * | orderType
753 | | ));
754 | | }
755 | |
756 | | // @dev key for whether claim funding fees is disabled
757 | | // @param the claim funding fees module
758 | * | function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {
759 | * | return keccak256(abi.encode(
760 | | CLAIM_FUNDING_FEES_FEATURE_DISABLED,
761 | * | module
762 | | ));
763 | | }
764 | |
765 | | // @dev key for whether claim colltareral is disabled
766 | | // @param the claim funding fees module
767 | | function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {
768 | | return keccak256(abi.encode(
769 | | CLAIM_COLLATERAL_FEATURE_DISABLED,
770 | | module
771 | | ));
772 | | }
773 | |
774 | | // @dev key for whether claim affiliate rewards is disabled
775 | | // @param the claim affiliate rewards module
776 | | function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {
777 | | return keccak256(abi.encode(
778 | | CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,
779 | | module
780 | | ));
781 | | }
782 | |
783 | | // @dev key for whether claim ui fees is disabled
784 | | // @param the claim ui fees module
785 | | function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {
786 | | return keccak256(abi.encode(
787 | | CLAIM_UI_FEES_FEATURE_DISABLED,
788 | | module
789 | | ));
790 | | }
791 | |
792 | | // @dev key for whether subaccounts are disabled
793 | | // @param the subaccount module
794 | | function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {
795 | | return keccak256(abi.encode(
796 | | SUBACCOUNT_FEATURE_DISABLED,
797 | | module
798 | | ));
799 | | }
800 | |
801 | | // @dev key for ui fee factor
802 | | // @param account the fee receiver account
803 | | // @return key for ui fee factor
804 | * | function uiFeeFactorKey(address account) internal pure returns (bytes32) {
805 | * | return keccak256(abi.encode(
806 | | UI_FEE_FACTOR,
807 | * | account
808 | | ));
809 | | }
810 | |
811 | | // @dev key for whether an oracle provider is enabled
812 | | // @param provider the oracle provider
813 | | // @return key for whether an oracle provider is enabled
814 | * | function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {
815 | * | return keccak256(abi.encode(
816 | | IS_ORACLE_PROVIDER_ENABLED,
817 | * | provider
818 | | ));
819 | | }
820 | |
821 | | // @dev key for whether an oracle provider is allowed to be used for atomic actions
822 | | // @param provider the oracle provider
823 | | // @return key for whether an oracle provider is allowed to be used for atomic actions
824 | * | function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {
825 | * | return keccak256(abi.encode(
826 | | IS_ATOMIC_ORACLE_PROVIDER,
827 | * | provider
828 | | ));
829 | | }
830 | |
831 | | // @dev key for oracle timestamp adjustment
832 | | // @param provider the oracle provider
833 | | // @param token the token
834 | | // @return key for oracle timestamp adjustment
835 | | function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {
836 | | return keccak256(abi.encode(
837 | | ORACLE_TIMESTAMP_ADJUSTMENT,
838 | | provider,
839 | | token
840 | | ));
841 | | }
842 | |
843 | | // @dev key for oracle provider for token
844 | | // @param token the token
845 | | // @return key for oracle provider for token
846 | * | function oracleProviderForTokenKey(address token) internal pure returns (bytes32) {
847 | * | return keccak256(abi.encode(
848 | | ORACLE_PROVIDER_FOR_TOKEN,
849 | * | token
850 | | ));
851 | | }
852 | |
853 | | // @dev key for gas to forward for token transfer
854 | | // @param the token to check
855 | | // @return key for gas to forward for token transfer
856 | * | function tokenTransferGasLimit(address token) internal pure returns (bytes32) {
857 | * | return keccak256(abi.encode(
858 | | TOKEN_TRANSFER_GAS_LIMIT,
859 | * | token
860 | | ));
861 | | }
862 | |
863 | | // @dev the default callback contract
864 | | // @param account the user's account
865 | | // @param market the address of the market
866 | | // @param callbackContract the callback contract
867 | * | function savedCallbackContract(address account, address market) internal pure returns (bytes32) {
868 | * | return keccak256(abi.encode(
869 | | SAVED_CALLBACK_CONTRACT,
870 | * | account,
871 | * | market
872 | | ));
873 | | }
874 | |
875 | | // @dev the min collateral factor key
876 | | // @param the market for the min collateral factor
877 | * | function minCollateralFactorKey(address market) internal pure returns (bytes32) {
878 | * | return keccak256(abi.encode(
879 | | MIN_COLLATERAL_FACTOR,
880 | * | market
881 | | ));
882 | | }
883 | |
884 | | // @dev the min collateral factor for open interest multiplier key
885 | | // @param the market for the factor
886 | * | function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {
887 | * | return keccak256(abi.encode(
888 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,
889 | * | market,
890 | * | isLong
891 | | ));
892 | | }
893 | |
894 | | // @dev the key for the virtual token id
895 | | // @param the token to get the virtual id for
896 | * | function virtualTokenIdKey(address token) internal pure returns (bytes32) {
897 | * | return keccak256(abi.encode(
898 | | VIRTUAL_TOKEN_ID,
899 | * | token
900 | | ));
901 | | }
902 | |
903 | | // @dev the key for the virtual market id
904 | | // @param the market to get the virtual id for
905 | * | function virtualMarketIdKey(address market) internal pure returns (bytes32) {
906 | * | return keccak256(abi.encode(
907 | | VIRTUAL_MARKET_ID,
908 | * | market
909 | | ));
910 | | }
911 | |
912 | | // @dev the key for the virtual inventory for positions
913 | | // @param the virtualTokenId the virtual token id
914 | | function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {
915 | | return keccak256(abi.encode(
916 | | VIRTUAL_INVENTORY_FOR_POSITIONS,
917 | | virtualTokenId
918 | | ));
919 | | }
920 | |
921 | | // @dev the key for the virtual inventory for swaps
922 | | // @param the virtualMarketId the virtual market id
923 | | // @param the token to check the inventory for
924 | | function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {
925 | | return keccak256(abi.encode(
926 | | VIRTUAL_INVENTORY_FOR_SWAPS,
927 | | virtualMarketId,
928 | | isLongToken
929 | | ));
930 | | }
931 | |
932 | | // @dev key for position impact factor
933 | | // @param market the market address to check
934 | | // @param isPositive whether the impact is positive or negative
935 | | // @return key for position impact factor
936 | * | function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
937 | * | return keccak256(abi.encode(
938 | | POSITION_IMPACT_FACTOR,
939 | * | market,
940 | * | isPositive
941 | | ));
942 | | }
943 | |
944 | | // @dev key for position impact exponent factor
945 | | // @param market the market address to check
946 | | // @return key for position impact exponent factor
947 | * | function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {
948 | * | return keccak256(abi.encode(
949 | | POSITION_IMPACT_EXPONENT_FACTOR,
950 | * | market
951 | | ));
952 | | }
953 | |
954 | | // @dev key for the max position impact factor
955 | | // @param market the market address to check
956 | | // @return key for the max position impact factor
957 | * | function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
958 | * | return keccak256(abi.encode(
959 | | MAX_POSITION_IMPACT_FACTOR,
960 | * | market,
961 | * | isPositive
962 | | ));
963 | | }
964 | |
965 | | // @dev key for the max position impact factor for liquidations
966 | | // @param market the market address to check
967 | | // @return key for the max position impact factor
968 | | function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {
969 | | return keccak256(abi.encode(
970 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,
971 | | market
972 | | ));
973 | | }
974 | |
975 | | // @dev key for position fee factor
976 | | // @param market the market address to check
977 | | // @param forPositiveImpact whether the fee is for an action that has a positive price impact
978 | | // @return key for position fee factor
979 | * | function positionFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
980 | * | return keccak256(abi.encode(
981 | | POSITION_FEE_FACTOR,
982 | * | market,
983 | * | forPositiveImpact
984 | | ));
985 | | }
986 | |
987 | | // @dev key for swap impact factor
988 | | // @param market the market address to check
989 | | // @param isPositive whether the impact is positive or negative
990 | | // @return key for swap impact factor
991 | * | function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
992 | * | return keccak256(abi.encode(
993 | | SWAP_IMPACT_FACTOR,
994 | * | market,
995 | * | isPositive
996 | | ));
997 | | }
998 | |
999 | | // @dev key for swap impact exponent factor
1000 | | // @param market the market address to check
1001 | | // @return key for swap impact exponent factor
1002 | * | function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {
1003 | * | return keccak256(abi.encode(
1004 | | SWAP_IMPACT_EXPONENT_FACTOR,
1005 | * | market
1006 | | ));
1007 | | }
1008 | |
1009 | |
1010 | | // @dev key for swap fee factor
1011 | | // @param market the market address to check
1012 | | // @return key for swap fee factor
1013 | * | function swapFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
1014 | * | return keccak256(abi.encode(
1015 | | SWAP_FEE_FACTOR,
1016 | * | market,
1017 | * | forPositiveImpact
1018 | | ));
1019 | | }
1020 | |
1021 | | // @dev key for atomic swap fee factor
1022 | | // @param market the market address to check
1023 | | // @return key for atomic swap fee factor
1024 | * | function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {
1025 | * | return keccak256(abi.encode(
1026 | | ATOMIC_SWAP_FEE_FACTOR,
1027 | * | market
1028 | | ));
1029 | | }
1030 | |
1031 | | // @dev key for oracle type
1032 | | // @param token the token to check
1033 | | // @return key for oracle type
1034 | | function oracleTypeKey(address token) internal pure returns (bytes32) {
1035 | | return keccak256(abi.encode(
1036 | | ORACLE_TYPE,
1037 | | token
1038 | | ));
1039 | | }
1040 | |
1041 | | // @dev key for open interest
1042 | | // @param market the market to check
1043 | | // @param collateralToken the collateralToken to check
1044 | | // @param isLong whether to check the long or short open interest
1045 | | // @return key for open interest
1046 | * | function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
1047 | * | return keccak256(abi.encode(
1048 | | OPEN_INTEREST,
1049 | * | market,
1050 | * | collateralToken,
1051 | * | isLong
1052 | | ));
1053 | | }
1054 | |
1055 | | // @dev key for open interest in tokens
1056 | | // @param market the market to check
1057 | | // @param collateralToken the collateralToken to check
1058 | | // @param isLong whether to check the long or short open interest
1059 | | // @return key for open interest in tokens
1060 | * | function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
1061 | * | return keccak256(abi.encode(
1062 | | OPEN_INTEREST_IN_TOKENS,
1063 | * | market,
1064 | * | collateralToken,
1065 | * | isLong
1066 | | ));
1067 | | }
1068 | |
1069 | | // @dev key for collateral sum for a market
1070 | | // @param market the market to check
1071 | | // @param collateralToken the collateralToken to check
1072 | | // @param isLong whether to check the long or short open interest
1073 | | // @return key for collateral sum
1074 | * | function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
1075 | * | return keccak256(abi.encode(
1076 | | COLLATERAL_SUM,
1077 | * | market,
1078 | * | collateralToken,
1079 | * | isLong
1080 | | ));
1081 | | }
1082 | |
1083 | | // @dev key for amount of tokens in a market's pool
1084 | | // @param market the market to check
1085 | | // @param token the token to check
1086 | | // @return key for amount of tokens in a market's pool
1087 | * | function poolAmountKey(address market, address token) internal pure returns (bytes32) {
1088 | * | return keccak256(abi.encode(
1089 | | POOL_AMOUNT,
1090 | * | market,
1091 | * | token
1092 | | ));
1093 | | }
1094 | |
1095 | | // @dev the key for the max amount of pool tokens
1096 | | // @param market the market for the pool
1097 | | // @param token the token for the pool
1098 | * | function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {
1099 | * | return keccak256(abi.encode(
1100 | | MAX_POOL_AMOUNT,
1101 | * | market,
1102 | * | token
1103 | | ));
1104 | | }
1105 | |
1106 | | // @dev the key for the max usd of pool tokens for deposits
1107 | | // @param market the market for the pool
1108 | | // @param token the token for the pool
1109 | * | function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {
1110 | * | return keccak256(abi.encode(
1111 | | MAX_POOL_USD_FOR_DEPOSIT,
1112 | * | market,
1113 | * | token
1114 | | ));
1115 | | }
1116 | |
1117 | | // @dev the key for the max open interest
1118 | | // @param market the market for the pool
1119 | | // @param isLong whether the key is for the long or short side
1120 | * | function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {
1121 | * | return keccak256(abi.encode(
1122 | | MAX_OPEN_INTEREST,
1123 | * | market,
1124 | * | isLong
1125 | | ));
1126 | | }
1127 | |
1128 | | // @dev key for amount of tokens in a market's position impact pool
1129 | | // @param market the market to check
1130 | | // @return key for amount of tokens in a market's position impact pool
1131 | * | function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {
1132 | * | return keccak256(abi.encode(
1133 | | POSITION_IMPACT_POOL_AMOUNT,
1134 | * | market
1135 | | ));
1136 | | }
1137 | |
1138 | | // @dev key for min amount of tokens in a market's position impact pool
1139 | | // @param market the market to check
1140 | | // @return key for min amount of tokens in a market's position impact pool
1141 | | function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {
1142 | | return keccak256(abi.encode(
1143 | | MIN_POSITION_IMPACT_POOL_AMOUNT,
1144 | | market
1145 | | ));
1146 | | }
1147 | |
1148 | | // @dev key for position impact pool distribution rate
1149 | | // @param market the market to check
1150 | | // @return key for position impact pool distribution rate
1151 | * | function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {
1152 | * | return keccak256(abi.encode(
1153 | | POSITION_IMPACT_POOL_DISTRIBUTION_RATE,
1154 | * | market
1155 | | ));
1156 | | }
1157 | |
1158 | | // @dev key for position impact pool distributed at
1159 | | // @param market the market to check
1160 | | // @return key for position impact pool distributed at
1161 | * | function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {
1162 | * | return keccak256(abi.encode(
1163 | | POSITION_IMPACT_POOL_DISTRIBUTED_AT,
1164 | * | market
1165 | | ));
1166 | | }
1167 | |
1168 | | // @dev key for amount of tokens in a market's swap impact pool
1169 | | // @param market the market to check
1170 | | // @param token the token to check
1171 | | // @return key for amount of tokens in a market's swap impact pool
1172 | * | function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {
1173 | * | return keccak256(abi.encode(
1174 | | SWAP_IMPACT_POOL_AMOUNT,
1175 | * | market,
1176 | * | token
1177 | | ));
1178 | | }
1179 | |
1180 | | // @dev key for reserve factor
1181 | | // @param market the market to check
1182 | | // @param isLong whether to get the key for the long or short side
1183 | | // @return key for reserve factor
1184 | * | function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1185 | * | return keccak256(abi.encode(
1186 | | RESERVE_FACTOR,
1187 | * | market,
1188 | * | isLong
1189 | | ));
1190 | | }
1191 | |
1192 | | // @dev key for open interest reserve factor
1193 | | // @param market the market to check
1194 | | // @param isLong whether to get the key for the long or short side
1195 | | // @return key for open interest reserve factor
1196 | * | function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1197 | * | return keccak256(abi.encode(
1198 | | OPEN_INTEREST_RESERVE_FACTOR,
1199 | * | market,
1200 | * | isLong
1201 | | ));
1202 | | }
1203 | |
1204 | | // @dev key for max pnl factor
1205 | | // @param market the market to check
1206 | | // @param isLong whether to get the key for the long or short side
1207 | | // @return key for max pnl factor
1208 | * | function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {
1209 | * | return keccak256(abi.encode(
1210 | | MAX_PNL_FACTOR,
1211 | * | pnlFactorType,
1212 | * | market,
1213 | * | isLong
1214 | | ));
1215 | | }
1216 | |
1217 | | // @dev the key for min PnL factor after ADL
1218 | | // @param market the market for the pool
1219 | | // @param isLong whether the key is for the long or short side
1220 | * | function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {
1221 | * | return keccak256(abi.encode(
1222 | | MIN_PNL_FACTOR_AFTER_ADL,
1223 | * | market,
1224 | * | isLong
1225 | | ));
1226 | | }
1227 | |
1228 | | // @dev key for latest adl time
1229 | | // @param market the market to check
1230 | | // @param isLong whether to get the key for the long or short side
1231 | | // @return key for latest adl time
1232 | * | function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {
1233 | * | return keccak256(abi.encode(
1234 | | LATEST_ADL_AT,
1235 | * | market,
1236 | * | isLong
1237 | | ));
1238 | | }
1239 | |
1240 | | // @dev key for whether adl is enabled
1241 | | // @param market the market to check
1242 | | // @param isLong whether to get the key for the long or short side
1243 | | // @return key for whether adl is enabled
1244 | * | function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {
1245 | * | return keccak256(abi.encode(
1246 | | IS_ADL_ENABLED,
1247 | * | market,
1248 | * | isLong
1249 | | ));
1250 | | }
1251 | |
1252 | | // @dev key for funding factor
1253 | | // @param market the market to check
1254 | | // @return key for funding factor
1255 | * | function fundingFactorKey(address market) internal pure returns (bytes32) {
1256 | * | return keccak256(abi.encode(
1257 | | FUNDING_FACTOR,
1258 | * | market
1259 | | ));
1260 | | }
1261 | |
1262 | | // @dev the key for funding exponent
1263 | | // @param market the market for the pool
1264 | * | function fundingExponentFactorKey(address market) internal pure returns (bytes32) {
1265 | * | return keccak256(abi.encode(
1266 | | FUNDING_EXPONENT_FACTOR,
1267 | * | market
1268 | | ));
1269 | | }
1270 | |
1271 | | // @dev the key for saved funding factor
1272 | | // @param market the market for the pool
1273 | * | function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
1274 | * | return keccak256(abi.encode(
1275 | | SAVED_FUNDING_FACTOR_PER_SECOND,
1276 | * | market
1277 | | ));
1278 | | }
1279 | |
1280 | | // @dev the key for funding increase factor
1281 | | // @param market the market for the pool
1282 | * | function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {
1283 | * | return keccak256(abi.encode(
1284 | | FUNDING_INCREASE_FACTOR_PER_SECOND,
1285 | * | market
1286 | | ));
1287 | | }
1288 | |
1289 | | // @dev the key for funding decrease factor
1290 | | // @param market the market for the pool
1291 | | function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {
1292 | | return keccak256(abi.encode(
1293 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1294 | | market
1295 | | ));
1296 | | }
1297 | |
1298 | | // @dev the key for min funding factor
1299 | | // @param market the market for the pool
1300 | | function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
1301 | | return keccak256(abi.encode(
1302 | | MIN_FUNDING_FACTOR_PER_SECOND,
1303 | | market
1304 | | ));
1305 | | }
1306 | |
1307 | | // @dev the key for max funding factor
1308 | | // @param market the market for the pool
1309 | * | function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
1310 | * | return keccak256(abi.encode(
1311 | | MAX_FUNDING_FACTOR_PER_SECOND,
1312 | * | market
1313 | | ));
1314 | | }
1315 | |
1316 | | // @dev the key for threshold for stable funding
1317 | | // @param market the market for the pool
1318 | | function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {
1319 | | return keccak256(abi.encode(
1320 | | THRESHOLD_FOR_STABLE_FUNDING,
1321 | | market
1322 | | ));
1323 | | }
1324 | |
1325 | | // @dev the key for threshold for decreasing funding
1326 | | // @param market the market for the pool
1327 | | function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {
1328 | | return keccak256(abi.encode(
1329 | | THRESHOLD_FOR_DECREASE_FUNDING,
1330 | | market
1331 | | ));
1332 | | }
1333 | |
1334 | | // @dev key for funding fee amount per size
1335 | | // @param market the market to check
1336 | | // @param collateralToken the collateralToken to get the key for
1337 | | // @param isLong whether to get the key for the long or short side
1338 | | // @return key for funding fee amount per size
1339 | * | function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
1340 | * | return keccak256(abi.encode(
1341 | | FUNDING_FEE_AMOUNT_PER_SIZE,
1342 | * | market,
1343 | * | collateralToken,
1344 | * | isLong
1345 | | ));
1346 | | }
1347 | |
1348 | | // @dev key for claimabel funding amount per size
1349 | | // @param market the market to check
1350 | | // @param collateralToken the collateralToken to get the key for
1351 | | // @param isLong whether to get the key for the long or short side
1352 | | // @return key for claimable funding amount per size
1353 | * | function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
1354 | * | return keccak256(abi.encode(
1355 | | CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,
1356 | * | market,
1357 | * | collateralToken,
1358 | * | isLong
1359 | | ));
1360 | | }
1361 | |
1362 | | // @dev key for when funding was last updated
1363 | | // @param market the market to check
1364 | | // @return key for when funding was last updated
1365 | * | function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {
1366 | * | return keccak256(abi.encode(
1367 | | FUNDING_UPDATED_AT,
1368 | * | market
1369 | | ));
1370 | | }
1371 | |
1372 | | // @dev key for claimable funding amount
1373 | | // @param market the market to check
1374 | | // @param token the token to check
1375 | | // @return key for claimable funding amount
1376 | * | function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {
1377 | * | return keccak256(abi.encode(
1378 | | CLAIMABLE_FUNDING_AMOUNT,
1379 | * | market,
1380 | * | token
1381 | | ));
1382 | | }
1383 | |
1384 | | // @dev key for claimable funding amount by account
1385 | | // @param market the market to check
1386 | | // @param token the token to check
1387 | | // @param account the account to check
1388 | | // @return key for claimable funding amount
1389 | * | function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {
1390 | * | return keccak256(abi.encode(
1391 | | CLAIMABLE_FUNDING_AMOUNT,
1392 | * | market,
1393 | * | token,
1394 | * | account
1395 | | ));
1396 | | }
1397 | |
1398 | | // @dev key for claimable collateral amount
1399 | | // @param market the market to check
1400 | | // @param token the token to check
1401 | | // @param account the account to check
1402 | | // @param timeKey the time key for the claimable amount
1403 | | // @return key for claimable funding amount
1404 | * | function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {
1405 | * | return keccak256(abi.encode(
1406 | | CLAIMABLE_COLLATERAL_AMOUNT,
1407 | * | market,
1408 | * | token
1409 | | ));
1410 | | }
1411 | |
1412 | | // @dev key for claimable collateral amount for a timeKey for an account
1413 | | // @param market the market to check
1414 | | // @param token the token to check
1415 | | // @param account the account to check
1416 | | // @param timeKey the time key for the claimable amount
1417 | | // @return key for claimable funding amount
1418 | | function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
1419 | | return keccak256(abi.encode(
1420 | | CLAIMABLE_COLLATERAL_AMOUNT,
1421 | | market,
1422 | | token,
1423 | | timeKey,
1424 | | account
1425 | | ));
1426 | | }
1427 | |
1428 | | // @dev key for claimable collateral factor for a timeKey
1429 | | // @param market the market to check
1430 | | // @param token the token to check
1431 | | // @param timeKey the time key for the claimable amount
1432 | | // @return key for claimable funding amount
1433 | | function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {
1434 | | return keccak256(abi.encode(
1435 | | CLAIMABLE_COLLATERAL_FACTOR,
1436 | | market,
1437 | | token,
1438 | | timeKey
1439 | | ));
1440 | | }
1441 | |
1442 | | // @dev key for claimable collateral factor for a timeKey for an account
1443 | | // @param market the market to check
1444 | | // @param token the token to check
1445 | | // @param timeKey the time key for the claimable amount
1446 | | // @param account the account to check
1447 | | // @return key for claimable funding amount
1448 | | function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
1449 | | return keccak256(abi.encode(
1450 | | CLAIMABLE_COLLATERAL_FACTOR,
1451 | | market,
1452 | | token,
1453 | | timeKey,
1454 | | account
1455 | | ));
1456 | | }
1457 | |
1458 | | // @dev key for claimable collateral factor
1459 | | // @param market the market to check
1460 | | // @param token the token to check
1461 | | // @param account the account to check
1462 | | // @param timeKey the time key for the claimable amount
1463 | | // @return key for claimable funding amount
1464 | | function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
1465 | | return keccak256(abi.encode(
1466 | | CLAIMED_COLLATERAL_AMOUNT,
1467 | | market,
1468 | | token,
1469 | | timeKey,
1470 | | account
1471 | | ));
1472 | | }
1473 | |
1474 | | // @dev key for optimal usage factor
1475 | | // @param market the market to check
1476 | | // @param isLong whether to get the key for the long or short side
1477 | | // @return key for optimal usage factor
1478 | * | function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1479 | * | return keccak256(abi.encode(
1480 | | OPTIMAL_USAGE_FACTOR,
1481 | * | market,
1482 | * | isLong
1483 | | ));
1484 | | }
1485 | |
1486 | | // @dev key for base borrowing factor
1487 | | // @param market the market to check
1488 | | // @param isLong whether to get the key for the long or short side
1489 | | // @return key for base borrowing factor
1490 | | function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1491 | | return keccak256(abi.encode(
1492 | | BASE_BORROWING_FACTOR,
1493 | | market,
1494 | | isLong
1495 | | ));
1496 | | }
1497 | |
1498 | | // @dev key for above optimal usage borrowing factor
1499 | | // @param market the market to check
1500 | | // @param isLong whether to get the key for the long or short side
1501 | | // @return key for above optimal usage borrowing factor
1502 | | function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1503 | | return keccak256(abi.encode(
1504 | | ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,
1505 | | market,
1506 | | isLong
1507 | | ));
1508 | | }
1509 | |
1510 | | // @dev key for borrowing factor
1511 | | // @param market the market to check
1512 | | // @param isLong whether to get the key for the long or short side
1513 | | // @return key for borrowing factor
1514 | * | function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1515 | * | return keccak256(abi.encode(
1516 | | BORROWING_FACTOR,
1517 | * | market,
1518 | * | isLong
1519 | | ));
1520 | | }
1521 | |
1522 | | // @dev the key for borrowing exponent
1523 | | // @param market the market for the pool
1524 | | // @param isLong whether to get the key for the long or short side
1525 | * | function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1526 | * | return keccak256(abi.encode(
1527 | | BORROWING_EXPONENT_FACTOR,
1528 | * | market,
1529 | * | isLong
1530 | | ));
1531 | | }
1532 | |
1533 | | // @dev key for cumulative borrowing factor
1534 | | // @param market the market to check
1535 | | // @param isLong whether to get the key for the long or short side
1536 | | // @return key for cumulative borrowing factor
1537 | * | function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
1538 | * | return keccak256(abi.encode(
1539 | | CUMULATIVE_BORROWING_FACTOR,
1540 | * | market,
1541 | * | isLong
1542 | | ));
1543 | | }
1544 | |
1545 | | // @dev key for cumulative borrowing factor updated at
1546 | | // @param market the market to check
1547 | | // @param isLong whether to get the key for the long or short side
1548 | | // @return key for cumulative borrowing factor updated at
1549 | * | function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {
1550 | * | return keccak256(abi.encode(
1551 | | CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,
1552 | * | market,
1553 | * | isLong
1554 | | ));
1555 | | }
1556 | |
1557 | | // @dev key for total borrowing amount
1558 | | // @param market the market to check
1559 | | // @param isLong whether to get the key for the long or short side
1560 | | // @return key for total borrowing amount
1561 | * | function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {
1562 | * | return keccak256(abi.encode(
1563 | | TOTAL_BORROWING,
1564 | * | market,
1565 | * | isLong
1566 | | ));
1567 | | }
1568 | |
1569 | | // @dev key for affiliate reward amount
1570 | | // @param market the market to check
1571 | | // @param token the token to get the key for
1572 | | // @param account the account to get the key for
1573 | | // @return key for affiliate reward amount
1574 | * | function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {
1575 | * | return keccak256(abi.encode(
1576 | | AFFILIATE_REWARD,
1577 | * | market,
1578 | * | token
1579 | | ));
1580 | | }
1581 | |
1582 | | function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
1583 | | return keccak256(abi.encode(
1584 | | MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,
1585 | | account,
1586 | | subaccount,
1587 | | actionType
1588 | | ));
1589 | | }
1590 | |
1591 | | function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
1592 | | return keccak256(abi.encode(
1593 | | SUBACCOUNT_ACTION_COUNT,
1594 | | account,
1595 | | subaccount,
1596 | | actionType
1597 | | ));
1598 | | }
1599 | |
1600 | | function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {
1601 | | return keccak256(abi.encode(
1602 | | SUBACCOUNT_AUTO_TOP_UP_AMOUNT,
1603 | | account,
1604 | | subaccount
1605 | | ));
1606 | | }
1607 | |
1608 | | // @dev key for affiliate reward amount for an account
1609 | | // @param market the market to check
1610 | | // @param token the token to get the key for
1611 | | // @param account the account to get the key for
1612 | | // @return key for affiliate reward amount
1613 | | function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {
1614 | | return keccak256(abi.encode(
1615 | | AFFILIATE_REWARD,
1616 | | market,
1617 | | token,
1618 | | account
1619 | | ));
1620 | | }
1621 | |
1622 | | // @dev key for is market disabled
1623 | | // @param market the market to check
1624 | | // @return key for is market disabled
1625 | * | function isMarketDisabledKey(address market) internal pure returns (bytes32) {
1626 | * | return keccak256(abi.encode(
1627 | | IS_MARKET_DISABLED,
1628 | * | market
1629 | | ));
1630 | | }
1631 | |
1632 | | // @dev key for min market tokens for first deposit
1633 | | // @param market the market to check
1634 | | // @return key for min market tokens for first deposit
1635 | | function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {
1636 | | return keccak256(abi.encode(
1637 | | MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,
1638 | | market
1639 | | ));
1640 | | }
1641 | |
1642 | | // @dev key for price feed address
1643 | | // @param token the token to get the key for
1644 | | // @return key for price feed address
1645 | | function priceFeedKey(address token) internal pure returns (bytes32) {
1646 | | return keccak256(abi.encode(
1647 | | PRICE_FEED,
1648 | | token
1649 | | ));
1650 | | }
1651 | |
1652 | | // @dev key for data stream feed ID
1653 | | // @param token the token to get the key for
1654 | | // @return key for data stream feed ID
1655 | | function dataStreamIdKey(address token) internal pure returns (bytes32) {
1656 | | return keccak256(abi.encode(
1657 | | DATA_STREAM_ID,
1658 | | token
1659 | | ));
1660 | | }
1661 | |
1662 | | // @dev key for data stream feed multiplier
1663 | | // @param token the token to get the key for
1664 | | // @return key for data stream feed multiplier
1665 | | function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {
1666 | | return keccak256(abi.encode(
1667 | | DATA_STREAM_MULTIPLIER,
1668 | | token
1669 | | ));
1670 | | }
1671 | |
1672 | | // @dev key for price feed multiplier
1673 | | // @param token the token to get the key for
1674 | | // @return key for price feed multiplier
1675 | | function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {
1676 | | return keccak256(abi.encode(
1677 | | PRICE_FEED_MULTIPLIER,
1678 | | token
1679 | | ));
1680 | | }
1681 | |
1682 | | function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {
1683 | | return keccak256(abi.encode(
1684 | | PRICE_FEED_HEARTBEAT_DURATION,
1685 | | token
1686 | | ));
1687 | | }
1688 | |
1689 | | // @dev key for stable price value
1690 | | // @param token the token to get the key for
1691 | | // @return key for stable price value
1692 | | function stablePriceKey(address token) internal pure returns (bytes32) {
1693 | | return keccak256(abi.encode(
1694 | | STABLE_PRICE,
1695 | | token
1696 | | ));
1697 | | }
1698 | |
1699 | | // @dev key for fee distributor swap token index
1700 | | // @param orderKey the swap order key
1701 | | // @return key for fee distributor swap token index
1702 | | function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {
1703 | | return keccak256(abi.encode(
1704 | | FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,
1705 | | orderKey
1706 | | ));
1707 | | }
1708 | |
1709 | | // @dev key for fee distributor swap fee batch key
1710 | | // @param orderKey the swap order key
1711 | | // @return key for fee distributor swap fee batch key
1712 | | function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {
1713 | | return keccak256(abi.encode(
1714 | | FEE_DISTRIBUTOR_SWAP_FEE_BATCH,
1715 | | orderKey
1716 | | ));
1717 | | }
1718 | |
1719 | | // @dev key for glv pending shift
1720 | | // @param glv the glv for the pending shift
1721 | | function glvPendingShiftKey(address glv) internal pure returns (bytes32) {
1722 | | return keccak256(abi.encode(GLV_PENDING_SHIFT, glv));
1723 | | }
1724 | |
1725 | | function glvPendingShiftBackrefKey(bytes32 shiftKey) internal pure returns (bytes32) {
1726 | | return keccak256(abi.encode(GLV_PENDING_SHIFT_BACKREF, shiftKey));
1727 | | }
1728 | |
1729 | | // @dev key for max market token balance for glv
1730 | | // @param glv the glv to check the market token balance for
1731 | | // @param market the market to check balance
1732 | | function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {
1733 | | return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));
1734 | | }
1735 | |
1736 | | // @dev key for is glv market disabled
1737 | | // @param glv the glv to check
1738 | | // @param market the market to check
1739 | | // @return key for is market disabled
1740 | | function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {
1741 | | return keccak256(abi.encode(
1742 | | IS_GLV_MARKET_DISABLED,
1743 | | glv,
1744 | | market
1745 | | ));
1746 | | }
1747 | | }
1748 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/Deposit.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title Deposit
6 | | // @dev Struct for deposits
7 | * | library Deposit {
8 | | // @dev there is a limit on the number of fields a struct can have when being passed
9 | | // or returned as a memory variable which can cause "Stack too deep" errors
10 | | // use sub-structs to avoid this issue
11 | | // @param addresses address values
12 | | // @param numbers number values
13 | | // @param flags boolean values
14 | | struct Props {
15 | | Addresses addresses;
16 | | Numbers numbers;
17 | | Flags flags;
18 | | }
19 | |
20 | | // @param account the account depositing liquidity
21 | | // @param receiver the address to send the liquidity tokens to
22 | | // @param callbackContract the callback contract
23 | | // @param uiFeeReceiver the ui fee receiver
24 | | // @param market the market to deposit to
25 | | struct Addresses {
26 | | address account;
27 | | address receiver;
28 | | address callbackContract;
29 | | address uiFeeReceiver;
30 | | address market;
31 | | address initialLongToken;
32 | | address initialShortToken;
33 | | address[] longTokenSwapPath;
34 | | address[] shortTokenSwapPath;
35 | | }
36 | |
37 | | // @param initialLongTokenAmount the amount of long tokens to deposit
38 | | // @param initialShortTokenAmount the amount of short tokens to deposit
39 | | // @param minMarketTokens the minimum acceptable number of liquidity tokens
40 | | // @param updatedAtBlock the block that the deposit was last updated at
41 | | // sending funds back to the user in case the deposit gets cancelled
42 | | // @param executionFee the execution fee for keepers
43 | | // @param callbackGasLimit the gas limit for the callbackContract
44 | | struct Numbers {
45 | | uint256 initialLongTokenAmount;
46 | | uint256 initialShortTokenAmount;
47 | | uint256 minMarketTokens;
48 | | uint256 updatedAtBlock;
49 | | uint256 updatedAtTime;
50 | | uint256 executionFee;
51 | | uint256 callbackGasLimit;
52 | | }
53 | |
54 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when
55 | | struct Flags {
56 | | bool shouldUnwrapNativeToken;
57 | | }
58 | |
59 | * | function account(Props memory props) internal pure returns (address) {
60 | * | return props.addresses.account;
61 | | }
62 | |
63 | * | function setAccount(Props memory props, address value) internal pure {
64 | * | props.addresses.account = value;
65 | | }
66 | |
67 | * | function receiver(Props memory props) internal pure returns (address) {
68 | * | return props.addresses.receiver;
69 | | }
70 | |
71 | * | function setReceiver(Props memory props, address value) internal pure {
72 | * | props.addresses.receiver = value;
73 | | }
74 | |
75 | * | function callbackContract(Props memory props) internal pure returns (address) {
76 | * | return props.addresses.callbackContract;
77 | | }
78 | |
79 | * | function setCallbackContract(Props memory props, address value) internal pure {
80 | * | props.addresses.callbackContract = value;
81 | | }
82 | |
83 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) {
84 | * | return props.addresses.uiFeeReceiver;
85 | | }
86 | |
87 | * | function setUiFeeReceiver(Props memory props, address value) internal pure {
88 | * | props.addresses.uiFeeReceiver = value;
89 | | }
90 | |
91 | * | function market(Props memory props) internal pure returns (address) {
92 | * | return props.addresses.market;
93 | | }
94 | |
95 | * | function setMarket(Props memory props, address value) internal pure {
96 | * | props.addresses.market = value;
97 | | }
98 | |
99 | * | function initialLongToken(Props memory props) internal pure returns (address) {
100 | * | return props.addresses.initialLongToken;
101 | | }
102 | |
103 | * | function setInitialLongToken(Props memory props, address value) internal pure {
104 | * | props.addresses.initialLongToken = value;
105 | | }
106 | |
107 | * | function initialShortToken(Props memory props) internal pure returns (address) {
108 | * | return props.addresses.initialShortToken;
109 | | }
110 | |
111 | * | function setInitialShortToken(Props memory props, address value) internal pure {
112 | * | props.addresses.initialShortToken = value;
113 | | }
114 | |
115 | * | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
116 | * | return props.addresses.longTokenSwapPath;
117 | | }
118 | |
119 | * | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {
120 | * | props.addresses.longTokenSwapPath = value;
121 | | }
122 | |
123 | * | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
124 | * | return props.addresses.shortTokenSwapPath;
125 | | }
126 | |
127 | * | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {
128 | * | props.addresses.shortTokenSwapPath = value;
129 | | }
130 | |
131 | * | function initialLongTokenAmount(Props memory props) internal pure returns (uint256) {
132 | * | return props.numbers.initialLongTokenAmount;
133 | | }
134 | |
135 | * | function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure {
136 | * | props.numbers.initialLongTokenAmount = value;
137 | | }
138 | |
139 | * | function initialShortTokenAmount(Props memory props) internal pure returns (uint256) {
140 | * | return props.numbers.initialShortTokenAmount;
141 | | }
142 | |
143 | * | function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure {
144 | * | props.numbers.initialShortTokenAmount = value;
145 | | }
146 | |
147 | * | function minMarketTokens(Props memory props) internal pure returns (uint256) {
148 | * | return props.numbers.minMarketTokens;
149 | | }
150 | |
151 | * | function setMinMarketTokens(Props memory props, uint256 value) internal pure {
152 | * | props.numbers.minMarketTokens = value;
153 | | }
154 | |
155 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) {
156 | * | return props.numbers.updatedAtBlock;
157 | | }
158 | |
159 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
160 | * | props.numbers.updatedAtBlock = value;
161 | | }
162 | |
163 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) {
164 | * | return props.numbers.updatedAtTime;
165 | | }
166 | |
167 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
168 | * | props.numbers.updatedAtTime = value;
169 | | }
170 | |
171 | * | function executionFee(Props memory props) internal pure returns (uint256) {
172 | * | return props.numbers.executionFee;
173 | | }
174 | |
175 | * | function setExecutionFee(Props memory props, uint256 value) internal pure {
176 | * | props.numbers.executionFee = value;
177 | | }
178 | |
179 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) {
180 | * | return props.numbers.callbackGasLimit;
181 | | }
182 | |
183 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
184 | * | props.numbers.callbackGasLimit = value;
185 | | }
186 | |
187 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {
188 | * | return props.flags.shouldUnwrapNativeToken;
189 | | }
190 | |
191 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {
192 | * | props.flags.shouldUnwrapNativeToken = value;
193 | | }
194 | | }
195 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./Deposit.sol";
10 | | import "./DepositUtils.sol";
11 | | import "../pricing/ISwapPricingUtils.sol";
12 | |
13 | * | library DepositEventUtils {
14 | | using Deposit for Deposit.Props;
15 | |
16 | | using EventUtils for EventUtils.AddressItems;
17 | | using EventUtils for EventUtils.UintItems;
18 | | using EventUtils for EventUtils.IntItems;
19 | | using EventUtils for EventUtils.BoolItems;
20 | | using EventUtils for EventUtils.Bytes32Items;
21 | | using EventUtils for EventUtils.BytesItems;
22 | | using EventUtils for EventUtils.StringItems;
23 | |
24 | * | function emitDepositCreated(
25 | | EventEmitter eventEmitter,
26 | | bytes32 key,
27 | | Deposit.Props memory deposit,
28 | | DepositUtils.DepositType depositType
29 | * | ) internal {
30 | * | EventUtils.EventLogData memory eventData;
31 | |
32 | * | eventData.addressItems.initItems(6);
33 | * | eventData.addressItems.setItem(0, "account", deposit.account());
34 | * | eventData.addressItems.setItem(1, "receiver", deposit.receiver());
35 | * | eventData.addressItems.setItem(2, "callbackContract", deposit.callbackContract());
36 | * | eventData.addressItems.setItem(3, "market", deposit.market());
37 | * | eventData.addressItems.setItem(4, "initialLongToken", deposit.initialLongToken());
38 | * | eventData.addressItems.setItem(5, "initialShortToken", deposit.initialShortToken());
39 | |
40 | * | eventData.addressItems.initArrayItems(2);
41 | * | eventData.addressItems.setItem(0, "longTokenSwapPath", deposit.longTokenSwapPath());
42 | * | eventData.addressItems.setItem(1, "shortTokenSwapPath", deposit.shortTokenSwapPath());
43 | |
44 | * | eventData.uintItems.initItems(8);
45 | * | eventData.uintItems.setItem(0, "initialLongTokenAmount", deposit.initialLongTokenAmount());
46 | * | eventData.uintItems.setItem(1, "initialShortTokenAmount", deposit.initialShortTokenAmount());
47 | * | eventData.uintItems.setItem(2, "minMarketTokens", deposit.minMarketTokens());
48 | * | eventData.uintItems.setItem(3, "updatedAtBlock", deposit.updatedAtBlock());
49 | * | eventData.uintItems.setItem(4, "updatedAtTime", deposit.updatedAtTime());
50 | * | eventData.uintItems.setItem(5, "executionFee", deposit.executionFee());
51 | * | eventData.uintItems.setItem(6, "callbackGasLimit", deposit.callbackGasLimit());
52 | * | eventData.uintItems.setItem(7, "depositType", uint256(depositType));
53 | |
54 | * | eventData.boolItems.initItems(1);
55 | * | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", deposit.shouldUnwrapNativeToken());
56 | |
57 | * | eventData.bytes32Items.initItems(1);
58 | * | eventData.bytes32Items.setItem(0, "key", key);
59 | |
60 | * | eventEmitter.emitEventLog2(
61 | | "DepositCreated",
62 | * | key,
63 | * | Cast.toBytes32(deposit.account()),
64 | * | eventData
65 | | );
66 | | }
67 | |
68 | * | function emitDepositExecuted(
69 | | EventEmitter eventEmitter,
70 | | bytes32 key,
71 | | address account,
72 | | uint256 longTokenAmount,
73 | | uint256 shortTokenAmount,
74 | | uint256 receivedMarketTokens,
75 | | ISwapPricingUtils.SwapPricingType swapPricingType
76 | * | ) internal {
77 | * | EventUtils.EventLogData memory eventData;
78 | |
79 | * | eventData.bytes32Items.initItems(1);
80 | * | eventData.bytes32Items.setItem(0, "key", key);
81 | |
82 | * | eventData.addressItems.initItems(1);
83 | * | eventData.addressItems.setItem(0, "account", account);
84 | |
85 | * | eventData.uintItems.initItems(4);
86 | * | eventData.uintItems.setItem(0, "longTokenAmount", longTokenAmount);
87 | * | eventData.uintItems.setItem(1, "shortTokenAmount", shortTokenAmount);
88 | * | eventData.uintItems.setItem(2, "receivedMarketTokens", receivedMarketTokens);
89 | * | eventData.uintItems.setItem(3, "swapPricingType", uint256(swapPricingType));
90 | |
91 | * | eventEmitter.emitEventLog2(
92 | | "DepositExecuted",
93 | * | key,
94 | * | Cast.toBytes32(account),
95 | * | eventData
96 | | );
97 | | }
98 | |
99 | * | function emitDepositCancelled(
100 | | EventEmitter eventEmitter,
101 | | bytes32 key,
102 | | address account,
103 | | string memory reason,
104 | | bytes memory reasonBytes
105 | * | ) internal {
106 | * | EventUtils.EventLogData memory eventData;
107 | |
108 | * | eventData.bytes32Items.initItems(1);
109 | * | eventData.bytes32Items.setItem(0, "key", key);
110 | |
111 | * | eventData.addressItems.initItems(1);
112 | * | eventData.addressItems.setItem(0, "account", account);
113 | |
114 | * | eventData.stringItems.initItems(1);
115 | * | eventData.stringItems.setItem(0, "reason", reason);
116 | |
117 | * | eventData.bytesItems.initItems(1);
118 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
119 | |
120 | * | eventEmitter.emitEventLog2(
121 | | "DepositCancelled",
122 | * | key,
123 | * | Cast.toBytes32(account),
124 | * | eventData
125 | | );
126 | | }
127 | | }
128 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Deposit.sol";
9 | |
10 | | /**
11 | | * @title DepositStoreUtils
12 | | * @dev Library for deposit storage functions
13 | | */
14 | * | library DepositStoreUtils {
15 | | using Deposit for Deposit.Props;
16 | |
17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER"));
19 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
20 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
21 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET"));
22 | * | bytes32 internal constant INITIAL_LONG_TOKEN = keccak256(abi.encode("INITIAL_LONG_TOKEN"));
23 | * | bytes32 internal constant INITIAL_SHORT_TOKEN = keccak256(abi.encode("INITIAL_SHORT_TOKEN"));
24 | * | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH"));
25 | * | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH"));
26 | |
27 | * | bytes32 internal constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_LONG_TOKEN_AMOUNT"));
28 | * | bytes32 internal constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_SHORT_TOKEN_AMOUNT"));
29 | * | bytes32 internal constant MIN_MARKET_TOKENS = keccak256(abi.encode("MIN_MARKET_TOKENS"));
30 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
31 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME"));
32 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
33 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
34 | |
35 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
36 | |
37 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Deposit.Props memory) {
38 | * | Deposit.Props memory deposit;
39 | * | if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) {
40 | | return deposit;
41 | | }
42 | |
43 | * | deposit.setAccount(dataStore.getAddress(
44 | * | keccak256(abi.encode(key, ACCOUNT))
45 | | ));
46 | |
47 | * | deposit.setReceiver(dataStore.getAddress(
48 | * | keccak256(abi.encode(key, RECEIVER))
49 | | ));
50 | |
51 | * | deposit.setCallbackContract(dataStore.getAddress(
52 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
53 | | ));
54 | |
55 | * | deposit.setUiFeeReceiver(dataStore.getAddress(
56 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
57 | | ));
58 | |
59 | * | deposit.setMarket(dataStore.getAddress(
60 | * | keccak256(abi.encode(key, MARKET))
61 | | ));
62 | |
63 | * | deposit.setInitialLongToken(dataStore.getAddress(
64 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN))
65 | | ));
66 | |
67 | * | deposit.setInitialShortToken(dataStore.getAddress(
68 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))
69 | | ));
70 | |
71 | * | deposit.setLongTokenSwapPath(dataStore.getAddressArray(
72 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
73 | | ));
74 | |
75 | * | deposit.setShortTokenSwapPath(dataStore.getAddressArray(
76 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
77 | | ));
78 | |
79 | * | deposit.setInitialLongTokenAmount(dataStore.getUint(
80 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))
81 | | ));
82 | |
83 | * | deposit.setInitialShortTokenAmount(dataStore.getUint(
84 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))
85 | | ));
86 | |
87 | * | deposit.setMinMarketTokens(dataStore.getUint(
88 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS))
89 | | ));
90 | |
91 | * | deposit.setUpdatedAtBlock(dataStore.getUint(
92 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
93 | | ));
94 | |
95 | * | deposit.setUpdatedAtTime(dataStore.getUint(
96 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
97 | | ));
98 | |
99 | * | deposit.setExecutionFee(dataStore.getUint(
100 | * | keccak256(abi.encode(key, EXECUTION_FEE))
101 | | ));
102 | |
103 | * | deposit.setCallbackGasLimit(dataStore.getUint(
104 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
105 | | ));
106 | |
107 | * | deposit.setShouldUnwrapNativeToken(dataStore.getBool(
108 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
109 | | ));
110 | |
111 | * | return deposit;
112 | | }
113 | |
114 | * | function set(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) internal {
115 | * | dataStore.addBytes32(
116 | | Keys.DEPOSIT_LIST,
117 | * | key
118 | | );
119 | |
120 | * | dataStore.addBytes32(
121 | * | Keys.accountDepositListKey(deposit.account()),
122 | * | key
123 | | );
124 | |
125 | * | dataStore.setAddress(
126 | * | keccak256(abi.encode(key, ACCOUNT)),
127 | * | deposit.account()
128 | | );
129 | |
130 | * | dataStore.setAddress(
131 | * | keccak256(abi.encode(key, RECEIVER)),
132 | * | deposit.receiver()
133 | | );
134 | |
135 | * | dataStore.setAddress(
136 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)),
137 | * | deposit.callbackContract()
138 | | );
139 | |
140 | * | dataStore.setAddress(
141 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)),
142 | * | deposit.uiFeeReceiver()
143 | | );
144 | |
145 | * | dataStore.setAddress(
146 | * | keccak256(abi.encode(key, MARKET)),
147 | * | deposit.market()
148 | | );
149 | |
150 | * | dataStore.setAddress(
151 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)),
152 | * | deposit.initialLongToken()
153 | | );
154 | |
155 | * | dataStore.setAddress(
156 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)),
157 | * | deposit.initialShortToken()
158 | | );
159 | |
160 | * | dataStore.setAddressArray(
161 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),
162 | * | deposit.longTokenSwapPath()
163 | | );
164 | |
165 | * | dataStore.setAddressArray(
166 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),
167 | * | deposit.shortTokenSwapPath()
168 | | );
169 | |
170 | * | dataStore.setUint(
171 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)),
172 | * | deposit.initialLongTokenAmount()
173 | | );
174 | |
175 | * | dataStore.setUint(
176 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)),
177 | * | deposit.initialShortTokenAmount()
178 | | );
179 | |
180 | * | dataStore.setUint(
181 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS)),
182 | * | deposit.minMarketTokens()
183 | | );
184 | |
185 | * | dataStore.setUint(
186 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
187 | * | deposit.updatedAtBlock()
188 | | );
189 | |
190 | * | dataStore.setUint(
191 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)),
192 | * | deposit.updatedAtTime()
193 | | );
194 | |
195 | * | dataStore.setUint(
196 | * | keccak256(abi.encode(key, EXECUTION_FEE)),
197 | * | deposit.executionFee()
198 | | );
199 | |
200 | * | dataStore.setUint(
201 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
202 | * | deposit.callbackGasLimit()
203 | | );
204 | |
205 | * | dataStore.setBool(
206 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
207 | * | deposit.shouldUnwrapNativeToken()
208 | | );
209 | | }
210 | |
211 | * | function remove(DataStore dataStore, bytes32 key, address account) internal {
212 | * | if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) {
213 | | revert Errors.DepositNotFound(key);
214 | | }
215 | |
216 | * | dataStore.removeBytes32(
217 | | Keys.DEPOSIT_LIST,
218 | * | key
219 | | );
220 | |
221 | * | dataStore.removeBytes32(
222 | * | Keys.accountDepositListKey(account),
223 | * | key
224 | | );
225 | |
226 | * | dataStore.removeAddress(
227 | * | keccak256(abi.encode(key, ACCOUNT))
228 | | );
229 | |
230 | * | dataStore.removeAddress(
231 | * | keccak256(abi.encode(key, RECEIVER))
232 | | );
233 | |
234 | * | dataStore.removeAddress(
235 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
236 | | );
237 | |
238 | * | dataStore.removeAddress(
239 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
240 | | );
241 | |
242 | * | dataStore.removeAddress(
243 | * | keccak256(abi.encode(key, MARKET))
244 | | );
245 | |
246 | * | dataStore.removeAddress(
247 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN))
248 | | );
249 | |
250 | * | dataStore.removeAddress(
251 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))
252 | | );
253 | |
254 | * | dataStore.removeAddressArray(
255 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
256 | | );
257 | |
258 | * | dataStore.removeAddressArray(
259 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
260 | | );
261 | |
262 | * | dataStore.removeUint(
263 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))
264 | | );
265 | |
266 | * | dataStore.removeUint(
267 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))
268 | | );
269 | |
270 | * | dataStore.removeUint(
271 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS))
272 | | );
273 | |
274 | * | dataStore.removeUint(
275 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
276 | | );
277 | |
278 | * | dataStore.removeUint(
279 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
280 | | );
281 | |
282 | * | dataStore.removeUint(
283 | * | keccak256(abi.encode(key, EXECUTION_FEE))
284 | | );
285 | |
286 | * | dataStore.removeUint(
287 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
288 | | );
289 | |
290 | * | dataStore.removeBool(
291 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
292 | | );
293 | | }
294 | |
295 | | function getDepositCount(DataStore dataStore) internal view returns (uint256) {
296 | | return dataStore.getBytes32Count(Keys.DEPOSIT_LIST);
297 | | }
298 | |
299 | | function getDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
300 | | return dataStore.getBytes32ValuesAt(Keys.DEPOSIT_LIST, start, end);
301 | | }
302 | |
303 | | function getAccountDepositCount(DataStore dataStore, address account) internal view returns (uint256) {
304 | | return dataStore.getBytes32Count(Keys.accountDepositListKey(account));
305 | | }
306 | |
307 | | function getAccountDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
308 | | return dataStore.getBytes32ValuesAt(Keys.accountDepositListKey(account), start, end);
309 | | }
310 | | }
311 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../event/EventEmitter.sol";
7 | |
8 | | import "./DepositVault.sol";
9 | | import "./DepositStoreUtils.sol";
10 | | import "./DepositEventUtils.sol";
11 | |
12 | | import "../nonce/NonceUtils.sol";
13 | |
14 | | import "../gas/GasUtils.sol";
15 | | import "../callback/CallbackUtils.sol";
16 | | import "../utils/AccountUtils.sol";
17 | |
18 | | // @title DepositUtils
19 | | // @dev Library for deposit functions, to help with the depositing of liquidity
20 | | // into a market in return for market tokens
21 | * | library DepositUtils {
22 | | using SafeCast for uint256;
23 | | using SafeCast for int256;
24 | |
25 | | using Price for Price.Props;
26 | | using Deposit for Deposit.Props;
27 | |
28 | | enum DepositType {
29 | | Normal,
30 | | Shift,
31 | | Glv
32 | | }
33 | |
34 | | // @dev CreateDepositParams struct used in createDeposit to avoid stack
35 | | // too deep errors
36 | | //
37 | | // @param receiver the address to send the market tokens to
38 | | // @param callbackContract the callback contract
39 | | // @param uiFeeReceiver the ui fee receiver
40 | | // @param market the market to deposit into
41 | | // @param minMarketTokens the minimum acceptable number of liquidity tokens
42 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when
43 | | // sending funds back to the user in case the deposit gets cancelled
44 | | // @param executionFee the execution fee for keepers
45 | | // @param callbackGasLimit the gas limit for the callbackContract
46 | | struct CreateDepositParams {
47 | | address receiver;
48 | | address callbackContract;
49 | | address uiFeeReceiver;
50 | | address market;
51 | | address initialLongToken;
52 | | address initialShortToken;
53 | | address[] longTokenSwapPath;
54 | | address[] shortTokenSwapPath;
55 | | uint256 minMarketTokens;
56 | | bool shouldUnwrapNativeToken;
57 | | uint256 executionFee;
58 | | uint256 callbackGasLimit;
59 | | }
60 | |
61 | | // @dev creates a deposit
62 | | //
63 | | // @param dataStore DataStore
64 | | // @param eventEmitter EventEmitter
65 | | // @param depositVault DepositVault
66 | | // @param account the depositing account
67 | | // @param params CreateDepositParams
68 | * | function createDeposit(
69 | | DataStore dataStore,
70 | | EventEmitter eventEmitter,
71 | | DepositVault depositVault,
72 | | address account,
73 | | CreateDepositParams memory params
74 | * | ) internal returns (bytes32) {
75 | * | AccountUtils.validateAccount(account);
76 | |
77 | * | Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, params.market);
78 | * | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath);
79 | * | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath);
80 | |
81 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would
82 | | // be non-zero, the initialShortTokenAmount would be zero
83 | * | uint256 initialLongTokenAmount = depositVault.recordTransferIn(params.initialLongToken);
84 | * | uint256 initialShortTokenAmount = depositVault.recordTransferIn(params.initialShortToken);
85 | |
86 | * | address wnt = TokenUtils.wnt(dataStore);
87 | |
88 | * | if (params.initialLongToken == wnt) {
89 | * | initialLongTokenAmount -= params.executionFee;
90 | * | } else if (params.initialShortToken == wnt) {
91 | | initialShortTokenAmount -= params.executionFee;
92 | * | } else {
93 | * | uint256 wntAmount = depositVault.recordTransferIn(wnt);
94 | * | if (wntAmount < params.executionFee) {
95 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);
96 | | }
97 | |
98 | * | params.executionFee = wntAmount;
99 | | }
100 | |
101 | * | if (initialLongTokenAmount == 0 && initialShortTokenAmount == 0) {
102 | | revert Errors.EmptyDepositAmounts();
103 | | }
104 | |
105 | * | AccountUtils.validateReceiver(params.receiver);
106 | |
107 | * | Deposit.Props memory deposit = Deposit.Props(
108 | * | Deposit.Addresses(
109 | * | account,
110 | * | params.receiver,
111 | * | params.callbackContract,
112 | * | params.uiFeeReceiver,
113 | * | market.marketToken,
114 | * | params.initialLongToken,
115 | * | params.initialShortToken,
116 | * | params.longTokenSwapPath,
117 | * | params.shortTokenSwapPath
118 | | ),
119 | * | Deposit.Numbers(
120 | * | initialLongTokenAmount,
121 | * | initialShortTokenAmount,
122 | * | params.minMarketTokens,
123 | * | Chain.currentBlockNumber(),
124 | * | Chain.currentTimestamp(),
125 | * | params.executionFee,
126 | * | params.callbackGasLimit
127 | | ),
128 | * | Deposit.Flags(
129 | * | params.shouldUnwrapNativeToken
130 | | )
131 | | );
132 | |
133 | * | CallbackUtils.validateCallbackGasLimit(dataStore, deposit.callbackGasLimit());
134 | |
135 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit);
136 | * | uint256 oraclePriceCount = GasUtils.estimateDepositOraclePriceCount(
137 | * | deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length
138 | | );
139 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount);
140 | |
141 | * | bytes32 key = NonceUtils.getNextKey(dataStore);
142 | |
143 | * | DepositStoreUtils.set(dataStore, key, deposit);
144 | |
145 | * | DepositEventUtils.emitDepositCreated(eventEmitter, key, deposit, DepositType.Normal);
146 | |
147 | * | return key;
148 | | }
149 | |
150 | | // @dev cancels a deposit, funds are sent back to the user
151 | | //
152 | | // @param dataStore DataStore
153 | | // @param eventEmitter EventEmitter
154 | | // @param depositVault DepositVault
155 | | // @param key the key of the deposit to cancel
156 | | // @param keeper the address of the keeper
157 | | // @param startingGas the starting gas amount
158 | * | function cancelDeposit(
159 | | DataStore dataStore,
160 | | EventEmitter eventEmitter,
161 | | DepositVault depositVault,
162 | | bytes32 key,
163 | | address keeper,
164 | | uint256 startingGas,
165 | | string memory reason,
166 | | bytes memory reasonBytes
167 | * | ) internal {
168 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
169 | * | startingGas -= gasleft() / 63;
170 | |
171 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);
172 | * | if (deposit.account() == address(0)) {
173 | | revert Errors.EmptyDeposit();
174 | | }
175 | |
176 | * | if (
177 | * | deposit.initialLongTokenAmount() == 0 &&
178 | | deposit.initialShortTokenAmount() == 0
179 | | ) {
180 | | revert Errors.EmptyDepositAmounts();
181 | | }
182 | |
183 | * | DepositStoreUtils.remove(dataStore, key, deposit.account());
184 | |
185 | * | if (deposit.initialLongTokenAmount() > 0) {
186 | * | depositVault.transferOut(
187 | * | deposit.initialLongToken(),
188 | * | deposit.account(),
189 | * | deposit.initialLongTokenAmount(),
190 | * | deposit.shouldUnwrapNativeToken()
191 | | );
192 | | }
193 | |
194 | * | if (deposit.initialShortTokenAmount() > 0) {
195 | * | depositVault.transferOut(
196 | * | deposit.initialShortToken(),
197 | * | deposit.account(),
198 | * | deposit.initialShortTokenAmount(),
199 | * | deposit.shouldUnwrapNativeToken()
200 | | );
201 | | }
202 | |
203 | * | DepositEventUtils.emitDepositCancelled(
204 | * | eventEmitter,
205 | * | key,
206 | * | deposit.account(),
207 | * | reason,
208 | * | reasonBytes
209 | | );
210 | |
211 | * | EventUtils.EventLogData memory eventData;
212 | * | CallbackUtils.afterDepositCancellation(key, deposit, eventData);
213 | |
214 | * | GasUtils.payExecutionFee(
215 | * | dataStore,
216 | * | eventEmitter,
217 | * | depositVault,
218 | * | key,
219 | * | deposit.callbackContract(),
220 | * | deposit.executionFee(),
221 | * | startingGas,
222 | * | GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length),
223 | * | keeper,
224 | * | deposit.receiver()
225 | | );
226 | | }
227 | | }
228 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositVault.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../bank/StrictBank.sol";
6 | |
7 | | // @title DepositVault
8 | | // @dev Vault for deposits
9 | * | contract DepositVault is StrictBank {
10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/ExecuteDepositUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../adl/AdlUtils.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../event/EventEmitter.sol";
9 | |
10 | | import "./DepositVault.sol";
11 | | import "./DepositStoreUtils.sol";
12 | | import "./DepositEventUtils.sol";
13 | |
14 | | import "../pricing/SwapPricingUtils.sol";
15 | | import "../oracle/Oracle.sol";
16 | | import "../oracle/OracleUtils.sol";
17 | |
18 | | import "../gas/GasUtils.sol";
19 | | import "../callback/CallbackUtils.sol";
20 | |
21 | | import "../utils/Array.sol";
22 | | import "../error/ErrorUtils.sol";
23 | |
24 | | // @title DepositUtils
25 | | // @dev Library for deposit functions, to help with the depositing of liquidity
26 | | // into a market in return for market tokens
27 | * | library ExecuteDepositUtils {
28 | | using SafeCast for uint256;
29 | | using SafeCast for int256;
30 | | using Array for uint256[];
31 | |
32 | | using Price for Price.Props;
33 | | using Deposit for Deposit.Props;
34 | |
35 | | using EventUtils for EventUtils.AddressItems;
36 | | using EventUtils for EventUtils.UintItems;
37 | | using EventUtils for EventUtils.IntItems;
38 | | using EventUtils for EventUtils.BoolItems;
39 | | using EventUtils for EventUtils.Bytes32Items;
40 | | using EventUtils for EventUtils.BytesItems;
41 | | using EventUtils for EventUtils.StringItems;
42 | |
43 | | // @dev ExecuteDepositParams struct used in executeDeposit to avoid stack
44 | | // too deep errors
45 | | struct ExecuteDepositParams {
46 | | DataStore dataStore;
47 | | EventEmitter eventEmitter;
48 | | DepositVault depositVault;
49 | | Oracle oracle;
50 | | bytes32 key;
51 | | address keeper;
52 | | uint256 startingGas;
53 | | ISwapPricingUtils.SwapPricingType swapPricingType;
54 | | bool includeVirtualInventoryImpact;
55 | | }
56 | |
57 | | // @dev _ExecuteDepositParams struct used in executeDeposit to avoid stack
58 | | // too deep errors
59 | | //
60 | | // @param market the market to deposit into
61 | | // @param account the depositing account
62 | | // @param receiver the account to send the market tokens to
63 | | // @param uiFeeReceiver the ui fee receiver account
64 | | // @param tokenIn the token to deposit, either the market.longToken or
65 | | // market.shortToken
66 | | // @param tokenOut the other token, if tokenIn is market.longToken then
67 | | // tokenOut is market.shortToken and vice versa
68 | | // @param tokenInPrice price of tokenIn
69 | | // @param tokenOutPrice price of tokenOut
70 | | // @param amount amount of tokenIn
71 | | // @param priceImpactUsd price impact in USD
72 | | struct _ExecuteDepositParams {
73 | | Market.Props market;
74 | | address account;
75 | | address receiver;
76 | | address uiFeeReceiver;
77 | | address tokenIn;
78 | | address tokenOut;
79 | | Price.Props tokenInPrice;
80 | | Price.Props tokenOutPrice;
81 | | uint256 amount;
82 | | int256 priceImpactUsd;
83 | | }
84 | |
85 | | struct ExecuteDepositCache {
86 | | uint256 requestExpirationTime;
87 | | uint256 maxOracleTimestamp;
88 | | Market.Props market;
89 | | MarketUtils.MarketPrices prices;
90 | | uint256 longTokenAmount;
91 | | uint256 shortTokenAmount;
92 | | uint256 longTokenUsd;
93 | | uint256 shortTokenUsd;
94 | | uint256 receivedMarketTokens;
95 | | int256 priceImpactUsd;
96 | | uint256 marketTokensSupply;
97 | | EventUtils.EventLogData callbackEventData;
98 | | }
99 | |
100 | | address internal constant RECEIVER_FOR_FIRST_DEPOSIT = address(1);
101 | |
102 | | // @dev executes a deposit
103 | | // @param params ExecuteDepositParams
104 | * | function executeDeposit(ExecuteDepositParams memory params, Deposit.Props memory deposit) internal returns (uint256 receivedMarketTokens) {
105 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
106 | * | params.startingGas -= gasleft() / 63;
107 | |
108 | * | DepositStoreUtils.remove(params.dataStore, params.key, deposit.account());
109 | |
110 | |
111 | * | if (deposit.account() == address(0)) {
112 | | revert Errors.EmptyDeposit();
113 | | }
114 | |
115 | * | if (params.oracle.minTimestamp() < deposit.updatedAtTime()) {
116 | * | revert Errors.OracleTimestampsAreSmallerThanRequired(
117 | * | params.oracle.minTimestamp(),
118 | * | deposit.updatedAtTime()
119 | | );
120 | | }
121 | |
122 | * | ExecuteDepositCache memory cache;
123 | * | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
124 | * | cache.maxOracleTimestamp = params.oracle.maxTimestamp();
125 | |
126 | * | if (cache.maxOracleTimestamp > deposit.updatedAtTime() + cache.requestExpirationTime) {
127 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
128 | * | cache.maxOracleTimestamp,
129 | * | deposit.updatedAtTime(),
130 | * | cache.requestExpirationTime
131 | | );
132 | | }
133 | |
134 | * | cache.market = MarketUtils.getEnabledMarket(params.dataStore, deposit.market());
135 | |
136 | * | _validateFirstDeposit(params, deposit, cache.market);
137 | |
138 | * | cache.prices = MarketUtils.getMarketPrices(params.oracle, cache.market);
139 | |
140 | * | MarketUtils.distributePositionImpactPool(
141 | * | params.dataStore,
142 | * | params.eventEmitter,
143 | * | cache.market.marketToken
144 | | );
145 | |
146 | * | PositionUtils.updateFundingAndBorrowingState(
147 | * | params.dataStore,
148 | * | params.eventEmitter,
149 | * | cache.market,
150 | * | cache.prices
151 | | );
152 | |
153 | | // deposits should improve the pool state but it should be checked if
154 | | // the max pnl factor for deposits is exceeded as this would lead to the
155 | | // price of the market token decreasing below a target minimum percentage
156 | | // due to pnl
157 | | // note that this is just a validation for deposits, there is no actual
158 | | // minimum price for a market token
159 | * | MarketUtils.validateMaxPnl(
160 | * | params.dataStore,
161 | * | cache.market,
162 | * | cache.prices,
163 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
164 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS
165 | | );
166 | |
167 | * | cache.longTokenAmount = swap(
168 | * | params,
169 | * | deposit.longTokenSwapPath(),
170 | * | deposit.initialLongToken(),
171 | * | deposit.initialLongTokenAmount(),
172 | * | cache.market.marketToken,
173 | * | cache.market.longToken,
174 | * | deposit.uiFeeReceiver()
175 | | );
176 | |
177 | * | cache.shortTokenAmount = swap(
178 | * | params,
179 | * | deposit.shortTokenSwapPath(),
180 | * | deposit.initialShortToken(),
181 | * | deposit.initialShortTokenAmount(),
182 | * | cache.market.marketToken,
183 | * | cache.market.shortToken,
184 | * | deposit.uiFeeReceiver()
185 | | );
186 | |
187 | * | if (cache.longTokenAmount == 0 && cache.shortTokenAmount == 0) {
188 | | revert Errors.EmptyDepositAmountsAfterSwap();
189 | | }
190 | |
191 | * | cache.longTokenUsd = cache.longTokenAmount * cache.prices.longTokenPrice.midPrice();
192 | * | cache.shortTokenUsd = cache.shortTokenAmount * cache.prices.shortTokenPrice.midPrice();
193 | |
194 | * | cache.priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
195 | * | SwapPricingUtils.GetPriceImpactUsdParams(
196 | * | params.dataStore,
197 | * | cache.market,
198 | * | cache.market.longToken,
199 | * | cache.market.shortToken,
200 | * | cache.prices.longTokenPrice.midPrice(),
201 | * | cache.prices.shortTokenPrice.midPrice(),
202 | * | cache.longTokenUsd.toInt256(),
203 | * | cache.shortTokenUsd.toInt256(),
204 | * | params.includeVirtualInventoryImpact
205 | | )
206 | | );
207 | |
208 | * | if (cache.longTokenAmount > 0) {
209 | * | _ExecuteDepositParams memory _params = _ExecuteDepositParams(
210 | * | cache.market,
211 | * | deposit.account(),
212 | * | deposit.receiver(),
213 | * | deposit.uiFeeReceiver(),
214 | * | cache.market.longToken,
215 | * | cache.market.shortToken,
216 | * | cache.prices.longTokenPrice,
217 | * | cache.prices.shortTokenPrice,
218 | * | cache.longTokenAmount,
219 | * | Precision.mulDiv(cache.priceImpactUsd, cache.longTokenUsd, cache.longTokenUsd + cache.shortTokenUsd)
220 | | );
221 | |
222 | * | cache.receivedMarketTokens += _executeDeposit(params, _params);
223 | | }
224 | |
225 | * | if (cache.shortTokenAmount > 0) {
226 | * | _ExecuteDepositParams memory _params = _ExecuteDepositParams(
227 | * | cache.market,
228 | * | deposit.account(),
229 | * | deposit.receiver(),
230 | * | deposit.uiFeeReceiver(),
231 | * | cache.market.shortToken,
232 | * | cache.market.longToken,
233 | * | cache.prices.shortTokenPrice,
234 | * | cache.prices.longTokenPrice,
235 | * | cache.shortTokenAmount,
236 | * | Precision.mulDiv(cache.priceImpactUsd, cache.shortTokenUsd, cache.longTokenUsd + cache.shortTokenUsd)
237 | | );
238 | |
239 | * | cache.receivedMarketTokens += _executeDeposit(params, _params);
240 | | }
241 | |
242 | * | if (cache.receivedMarketTokens < deposit.minMarketTokens()) {
243 | | revert Errors.MinMarketTokens(cache.receivedMarketTokens, deposit.minMarketTokens());
244 | | }
245 | |
246 | | // validate that internal state changes are correct before calling
247 | | // internal callbacks
248 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, cache.market);
249 | |
250 | * | DepositEventUtils.emitDepositExecuted(
251 | * | params.eventEmitter,
252 | * | params.key,
253 | * | deposit.account(),
254 | * | cache.longTokenAmount,
255 | * | cache.shortTokenAmount,
256 | * | cache.receivedMarketTokens,
257 | * | params.swapPricingType
258 | | );
259 | |
260 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
261 | * | params.dataStore,
262 | * | cache.market,
263 | * | cache.prices.indexTokenPrice,
264 | * | cache.prices.longTokenPrice,
265 | * | cache.prices.shortTokenPrice,
266 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
267 | * | true
268 | | );
269 | |
270 | * | cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(cache.market.marketToken)));
271 | |
272 | * | MarketEventUtils.emitMarketPoolValueUpdated(
273 | * | params.eventEmitter,
274 | * | keccak256(abi.encode("DEPOSIT")),
275 | * | params.key,
276 | * | cache.market.marketToken,
277 | * | poolValueInfo,
278 | * | cache.marketTokensSupply
279 | | );
280 | |
281 | * | cache.callbackEventData.uintItems.initItems(1);
282 | * | cache.callbackEventData.uintItems.setItem(0, "receivedMarketTokens", cache.receivedMarketTokens);
283 | * | CallbackUtils.afterDepositExecution(params.key, deposit, cache.callbackEventData);
284 | |
285 | * | GasUtils.payExecutionFee(
286 | * | params.dataStore,
287 | * | params.eventEmitter,
288 | * | params.depositVault,
289 | * | params.key,
290 | * | deposit.callbackContract(),
291 | * | deposit.executionFee(),
292 | * | params.startingGas,
293 | * | GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length),
294 | * | params.keeper,
295 | * | deposit.receiver()
296 | | );
297 | |
298 | * | return cache.receivedMarketTokens;
299 | | }
300 | |
301 | | // @dev executes a deposit
302 | | // @param params ExecuteDepositParams
303 | | // @param _params _ExecuteDepositParams
304 | * | function _executeDeposit(ExecuteDepositParams memory params, _ExecuteDepositParams memory _params) internal returns (uint256) {
305 | | // for markets where longToken == shortToken, the price impact factor should be set to zero
306 | | // in which case, the priceImpactUsd would always equal zero
307 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(
308 | * | params.dataStore,
309 | * | _params.market.marketToken,
310 | * | _params.amount,
311 | * | _params.priceImpactUsd > 0, // forPositiveImpact
312 | * | _params.uiFeeReceiver,
313 | * | params.swapPricingType
314 | | );
315 | |
316 | * | FeeUtils.incrementClaimableFeeAmount(
317 | * | params.dataStore,
318 | * | params.eventEmitter,
319 | * | _params.market.marketToken,
320 | * | _params.tokenIn,
321 | * | fees.feeReceiverAmount,
322 | | Keys.DEPOSIT_FEE_TYPE
323 | | );
324 | |
325 | * | FeeUtils.incrementClaimableUiFeeAmount(
326 | * | params.dataStore,
327 | * | params.eventEmitter,
328 | * | _params.uiFeeReceiver,
329 | * | _params.market.marketToken,
330 | * | _params.tokenIn,
331 | * | fees.uiFeeAmount,
332 | | Keys.UI_DEPOSIT_FEE_TYPE
333 | | );
334 | |
335 | * | SwapPricingUtils.emitSwapFeesCollected(
336 | * | params.eventEmitter,
337 | * | params.key,
338 | * | _params.market.marketToken,
339 | * | _params.tokenIn,
340 | * | _params.tokenInPrice.min,
341 | | Keys.DEPOSIT_FEE_TYPE,
342 | * | fees
343 | | );
344 | |
345 | * | uint256 mintAmount;
346 | |
347 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
348 | * | params.dataStore,
349 | * | _params.market,
350 | * | params.oracle.getPrimaryPrice(_params.market.indexToken),
351 | * | _params.tokenIn == _params.market.longToken ? _params.tokenInPrice : _params.tokenOutPrice,
352 | * | _params.tokenIn == _params.market.shortToken ? _params.tokenInPrice : _params.tokenOutPrice,
353 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
354 | * | true
355 | | );
356 | |
357 | * | if (poolValueInfo.poolValue < 0) {
358 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);
359 | | }
360 | |
361 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256();
362 | |
363 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(_params.market.marketToken)));
364 | |
365 | * | if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) {
366 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);
367 | | }
368 | |
369 | * | MarketEventUtils.emitMarketPoolValueInfo(
370 | * | params.eventEmitter,
371 | * | params.key,
372 | * | _params.market.marketToken,
373 | * | poolValueInfo,
374 | * | marketTokensSupply
375 | | );
376 | |
377 | | // the poolValue and marketTokensSupply is cached for the mintAmount calculation below
378 | | // so the effect of any positive price impact on the poolValue and marketTokensSupply
379 | | // would not be accounted for
380 | | //
381 | | // for most cases, this should not be an issue, since the poolValue and marketTokensSupply
382 | | // should have been proportionately increased
383 | | //
384 | | // e.g. if the poolValue is $100 and marketTokensSupply is 100, and there is a positive price impact
385 | | // of $10, the poolValue should have increased by $10 and the marketTokensSupply should have been increased by 10
386 | | //
387 | | // there is a case where this may be an issue which is when all tokens are withdrawn from an existing market
388 | | // and the marketTokensSupply is reset to zero, but the poolValue is not entirely zero
389 | | // the case where this happens should be very rare and during withdrawal the poolValue should be close to zero
390 | | //
391 | | // however, in case this occurs, the usdToMarketTokenAmount will mint an additional number of market tokens
392 | | // proportional to the existing poolValue
393 | | //
394 | | // since the poolValue and marketTokensSupply is cached, this could occur once during positive price impact
395 | | // and again when calculating the mintAmount
396 | | //
397 | | // to avoid this, set the priceImpactUsd to be zero for this case
398 | * | if (_params.priceImpactUsd > 0 && marketTokensSupply == 0) {
399 | | _params.priceImpactUsd = 0;
400 | | }
401 | |
402 | * | if (_params.priceImpactUsd > 0) {
403 | | // when there is a positive price impact factor,
404 | | // tokens from the swap impact pool are used to mint additional market tokens for the user
405 | | // for example, if 50,000 USDC is deposited and there is a positive price impact
406 | | // an additional 0.005 ETH may be used to mint market tokens
407 | | // the swap impact pool is decreased by the used amount
408 | | //
409 | | // priceImpactUsd is calculated based on pricing assuming only depositAmount of tokenIn
410 | | // was added to the pool
411 | | // since impactAmount of tokenOut is added to the pool here, the calculation of
412 | | // the price impact would not be entirely accurate
413 | | //
414 | | // it is possible that the addition of the positive impact amount of tokens into the pool
415 | | // could increase the imbalance of the pool, for most cases this should not be a significant
416 | | // change compared to the improvement of balance from the actual deposit
417 | | (int256 positiveImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(
418 | | params.dataStore,
419 | | params.eventEmitter,
420 | | _params.market.marketToken,
421 | | _params.tokenOut,
422 | | _params.tokenOutPrice,
423 | | _params.priceImpactUsd
424 | | );
425 | |
426 | | // calculate the usd amount using positiveImpactAmount since it may
427 | | // be capped by the max available amount in the impact pool
428 | | // use tokenOutPrice.max to get the USD value since the positiveImpactAmount
429 | | // was calculated using a USD value divided by tokenOutPrice.max
430 | | //
431 | | // for the initial deposit, the pool value and token supply would be zero
432 | | // so the market token price is treated as 1 USD
433 | | //
434 | | // it is possible for the pool value to be more than zero and the token supply
435 | | // to be zero, in that case, the market token price is also treated as 1 USD
436 | | mintAmount += MarketUtils.usdToMarketTokenAmount(
437 | | positiveImpactAmount.toUint256() * _params.tokenOutPrice.max,
438 | | poolValue,
439 | | marketTokensSupply
440 | | );
441 | |
442 | | // deposit the token out, that was withdrawn from the impact pool, to mint market tokens
443 | | MarketUtils.applyDeltaToPoolAmount(
444 | | params.dataStore,
445 | | params.eventEmitter,
446 | | _params.market,
447 | | _params.tokenOut,
448 | | positiveImpactAmount
449 | | );
450 | |
451 | | // MarketUtils.validatePoolUsdForDeposit is not called here
452 | | // this is to prevent unnecessary reverts
453 | | // for example, if the pool's long token is close to the deposit cap
454 | | // but the short token is not close to the cap, depositing the short
455 | | // token can lead to a positive price impact which can cause the
456 | | // long token's deposit cap to be exceeded
457 | | // in this case, it is preferrable that the pool can still be
458 | | // rebalanced even if the deposit cap may be exceeded
459 | |
460 | | MarketUtils.validatePoolAmount(
461 | | params.dataStore,
462 | | _params.market,
463 | | _params.tokenOut
464 | | );
465 | | }
466 | |
467 | * | if (_params.priceImpactUsd < 0) {
468 | | // when there is a negative price impact factor,
469 | | // less of the deposit amount is used to mint market tokens
470 | | // for example, if 10 ETH is deposited and there is a negative price impact
471 | | // only 9.995 ETH may be used to mint market tokens
472 | | // the remaining 0.005 ETH will be stored in the swap impact pool
473 | | (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(
474 | | params.dataStore,
475 | | params.eventEmitter,
476 | | _params.market.marketToken,
477 | | _params.tokenIn,
478 | | _params.tokenInPrice,
479 | | _params.priceImpactUsd
480 | | );
481 | |
482 | | fees.amountAfterFees -= (-negativeImpactAmount).toUint256();
483 | | }
484 | |
485 | * | mintAmount += MarketUtils.usdToMarketTokenAmount(
486 | * | fees.amountAfterFees * _params.tokenInPrice.min,
487 | * | poolValue,
488 | * | marketTokensSupply
489 | | );
490 | |
491 | * | MarketUtils.applyDeltaToPoolAmount(
492 | * | params.dataStore,
493 | * | params.eventEmitter,
494 | * | _params.market,
495 | * | _params.tokenIn,
496 | * | (fees.amountAfterFees + fees.feeAmountForPool).toInt256()
497 | | );
498 | |
499 | * | MarketUtils.validatePoolUsdForDeposit(
500 | * | params.dataStore,
501 | * | _params.market,
502 | * | _params.tokenIn,
503 | * | _params.tokenInPrice.max
504 | | );
505 | |
506 | * | MarketUtils.validatePoolAmount(
507 | * | params.dataStore,
508 | * | _params.market,
509 | * | _params.tokenIn
510 | | );
511 | |
512 | * | MarketToken(payable(_params.market.marketToken)).mint(_params.receiver, mintAmount);
513 | |
514 | * | return mintAmount;
515 | | }
516 | |
517 | * | function swap(
518 | | ExecuteDepositParams memory params,
519 | | address[] memory swapPath,
520 | | address initialToken,
521 | | uint256 inputAmount,
522 | | address market,
523 | | address expectedOutputToken,
524 | | address uiFeeReceiver
525 | * | ) internal returns (uint256) {
526 | * | Market.Props[] memory swapPathMarkets = MarketUtils.getSwapPathMarkets(
527 | * | params.dataStore,
528 | * | swapPath
529 | | );
530 | |
531 | * | (address outputToken, uint256 outputAmount) = SwapUtils.swap(
532 | * | SwapUtils.SwapParams(
533 | * | params.dataStore, // dataStore
534 | * | params.eventEmitter, // eventEmitter
535 | * | params.oracle, // oracle
536 | * | params.depositVault, // bank
537 | * | params.key, // key
538 | * | initialToken, // tokenIn
539 | * | inputAmount, // amountIn
540 | * | swapPathMarkets, // swapPathMarkets
541 | * | 0, // minOutputAmount
542 | * | market, // receiver
543 | * | uiFeeReceiver, // uiFeeReceiver
544 | * | false // shouldUnwrapNativeToken
545 | | )
546 | | );
547 | |
548 | * | if (outputToken != expectedOutputToken) {
549 | | revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken);
550 | | }
551 | |
552 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, swapPathMarkets);
553 | |
554 | * | return outputAmount;
555 | | }
556 | |
557 | | // this method validates that a specified minimum number of market tokens are locked
558 | | // this can be used to help ensure a minimum amount of liquidity for a market
559 | | // this also helps to prevent manipulation of the market token price by the first depositor
560 | | // since it may be possible to deposit a small amount of tokens on the first deposit
561 | | // to cause a high market token price due to rounding of the amount of tokens minted
562 | * | function _validateFirstDeposit(
563 | | ExecuteDepositParams memory params,
564 | | Deposit.Props memory deposit,
565 | | Market.Props memory market
566 | | ) internal view {
567 | * | uint256 initialMarketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
568 | |
569 | | // return if this is not the first deposit
570 | * | if (initialMarketTokensSupply != 0) { return; }
571 | |
572 | | uint256 minMarketTokens = params.dataStore.getUint(Keys.minMarketTokensForFirstDepositKey(market.marketToken));
573 | |
574 | | // return if there is no minMarketTokens requirement
575 | | if (minMarketTokens == 0) { return; }
576 | |
577 | | if (deposit.receiver() != RECEIVER_FOR_FIRST_DEPOSIT) {
578 | | revert Errors.InvalidReceiverForFirstDeposit(deposit.receiver(), RECEIVER_FOR_FIRST_DEPOSIT);
579 | | }
580 | |
581 | | if (deposit.minMarketTokens() < minMarketTokens) {
582 | | revert Errors.InvalidMinMarketTokensForFirstDeposit(deposit.minMarketTokens(), minMarketTokens);
583 | | }
584 | | }
585 | | }
586 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/error/ErrorUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | * | library ErrorUtils {
6 | | // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577
7 | * | function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {
8 | | // If the result length is less than 68, then the transaction either panicked or failed silently
9 | * | if (result.length < 68) {
10 | * | return ("", false);
11 | | }
12 | |
13 | * | bytes4 errorSelector = getErrorSelectorFromData(result);
14 | |
15 | | // 0x08c379a0 is the selector for Error(string)
16 | | // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/
17 | * | if (errorSelector == bytes4(0x08c379a0)) {
18 | | assembly {
19 | * | result := add(result, 0x04)
20 | | }
21 | |
22 | * | return (abi.decode(result, (string)), true);
23 | | }
24 | |
25 | | // error may be a custom error, return an empty string for this case
26 | * | return ("", false);
27 | | }
28 | |
29 | * | function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {
30 | * | bytes4 errorSelector;
31 | |
32 | | assembly {
33 | * | errorSelector := mload(add(data, 0x20))
34 | | }
35 | |
36 | * | return errorSelector;
37 | | }
38 | |
39 | | function revertWithParsedMessage(bytes memory result) internal pure {
40 | | (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);
41 | |
42 | | if (hasRevertMessage) {
43 | | revert(revertMessage);
44 | | } else {
45 | | revertWithCustomError(result);
46 | | }
47 | | }
48 | |
49 | * | function revertWithCustomError(bytes memory result) internal pure {
50 | | // referenced from https://ethereum.stackexchange.com/a/123588
51 | * | uint256 length = result.length;
52 | | assembly {
53 | * | revert(add(result, 0x20), length)
54 | | }
55 | | }
56 | | }
57 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/error/Errors.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | * | library Errors {
6 | | // AdlHandler errors
7 | | error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);
8 | | error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);
9 | | error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);
10 | |
11 | | // AdlUtils errors
12 | | error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);
13 | | error AdlNotEnabled();
14 | |
15 | | // AutoCancelUtils errors
16 | | error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);
17 | |
18 | | // Bank errors
19 | | error SelfTransferNotSupported(address receiver);
20 | | error InvalidNativeTokenSender(address msgSender);
21 | |
22 | | // BaseHandler errors
23 | | error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);
24 | |
25 | | // CallbackUtils errors
26 | | error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);
27 | | error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);
28 | |
29 | | // Config errors
30 | | error InvalidBaseKey(bytes32 baseKey);
31 | | error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);
32 | | error InvalidClaimableFactor(uint256 value);
33 | | error PriceFeedAlreadyExistsForToken(address token);
34 | | error DataStreamIdAlreadyExistsForToken(address token);
35 | | error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);
36 | |
37 | | // Timelock errors
38 | | error ActionAlreadySignalled();
39 | | error ActionNotSignalled();
40 | | error SignalTimeNotYetPassed(uint256 signalTime);
41 | | error InvalidTimelockDelay(uint256 timelockDelay);
42 | | error MaxTimelockDelayExceeded(uint256 timelockDelay);
43 | | error InvalidFeeReceiver(address receiver);
44 | | error InvalidOracleSigner(address receiver);
45 | |
46 | | // GlvDepositStoreUtils errors
47 | | error GlvDepositNotFound(bytes32 key);
48 | | // GlvDepositUtils errors
49 | | error EmptyGlvDepositAmounts();
50 | | error EmptyGlvDeposit();
51 | | // GlvUtils errors
52 | | error EmptyGlv(address glv);
53 | | error GlvUnsupportedMarket(address glv, address market);
54 | | error GlvDisabledMarket(address glv, address market);
55 | | error GlvMaxMarketTokenBalanceExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);
56 | | error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);
57 | | error GlvHasPendingShift(address glv);
58 | | error GlvShiftNotFound(bytes32 shiftKey);
59 | | error GlvInvalidReceiver(address glv, address receiver);
60 | | error GlvInvalidCallbackContract(address glvHandler, address callbackContract);
61 | | error GlvMarketAlreadyExists(address glv, address market);
62 | | error InvalidMarketTokenPrice(address market, int256 price);
63 | | // GlvFactory
64 | | error GlvAlreadyExists(address glv);
65 | |
66 | | // DepositStoreUtils errors
67 | | error DepositNotFound(bytes32 key);
68 | |
69 | | // DepositUtils errors
70 | | error EmptyDeposit();
71 | | error EmptyDepositAmounts();
72 | |
73 | | // ExecuteDepositUtils errors
74 | | error MinMarketTokens(uint256 received, uint256 expected);
75 | | error EmptyDepositAmountsAfterSwap();
76 | | error InvalidPoolValueForDeposit(int256 poolValue);
77 | | error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);
78 | | error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);
79 | | error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);
80 | |
81 | | // ExternalHandler errors
82 | | error ExternalCallFailed(bytes data);
83 | | error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);
84 | | error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);
85 | | error InvalidExternalCallTarget(address target);
86 | |
87 | | // FeeBatchStoreUtils errors
88 | | error FeeBatchNotFound(bytes32 key);
89 | |
90 | | // FeeDistributor errors
91 | | error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);
92 | | error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);
93 | | error InvalidSwapPathForV1(address[] path, address bridgingToken);
94 | |
95 | | // GlpMigrator errors
96 | | error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);
97 | | error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);
98 | |
99 | | // GlvHandler errors
100 | | error InvalidGlvDepositInitialShortToken(address initialLongToken, address initialShortToken);
101 | | error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);
102 | | error MinGlvTokens(uint256 received, uint256 expected);
103 | |
104 | | // OrderHandler errors
105 | | error OrderNotUpdatable(uint256 orderType);
106 | | error InvalidKeeperForFrozenOrder(address keeper);
107 | |
108 | | // FeatureUtils errors
109 | | error DisabledFeature(bytes32 key);
110 | |
111 | | // FeeHandler errors
112 | | error InvalidClaimFeesInput(uint256 marketsLength, uint256 tokensLength);
113 | |
114 | | // GasUtils errors
115 | | error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);
116 | | error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);
117 | | error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);
118 | | error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);
119 | | error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);
120 | |
121 | | // MarketFactory errors
122 | | error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);
123 | |
124 | | // MarketStoreUtils errors
125 | | error MarketNotFound(address key);
126 | |
127 | | // MarketUtils errors
128 | | error EmptyMarket();
129 | | error DisabledMarket(address market);
130 | | error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);
131 | | error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);
132 | | error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);
133 | | error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);
134 | | error UnableToGetOppositeToken(address inputToken, address market);
135 | | error UnexpectedTokenForVirtualInventory(address token, address market);
136 | | error EmptyMarketTokenSupply();
137 | | error InvalidSwapMarket(address market);
138 | | error UnableToGetCachedTokenPrice(address token, address market);
139 | | error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);
140 | | error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);
141 | | error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);
142 | | error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);
143 | | error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);
144 | | error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);
145 | | error UnableToGetBorrowingFactorEmptyPoolUsd();
146 | | error UnableToGetFundingFactorEmptyOpenInterest();
147 | | error InvalidPositionMarket(address market);
148 | | error InvalidCollateralTokenForMarket(address market, address token);
149 | | error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);
150 | | error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);
151 | | error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);
152 | | error EmptyAddressInMarketTokenBalanceValidation(address market, address token);
153 | | error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);
154 | | error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);
155 | | error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);
156 | | error UnexpectedPoolValue(int256 poolValue);
157 | |
158 | | // Oracle errors
159 | | error SequencerDown();
160 | | error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);
161 | | error EmptyValidatedPrices();
162 | | error InvalidOracleProvider(address provider);
163 | | error InvalidOracleProviderForToken(address provider, address expectedProvider);
164 | | error GmEmptySigner(uint256 signerIndex);
165 | | error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);
166 | | error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);
167 | | error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);
168 | | error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);
169 | | error EmptyDataStreamFeedId(address token);
170 | | error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);
171 | | error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);
172 | | error InvalidDataStreamPrices(address token, int192 bid, int192 ask);
173 | | error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);
174 | | error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);
175 | | error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);
176 | | error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);
177 | | error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);
178 | | error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);
179 | | error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);
180 | | error EmptyChainlinkPriceFeedMultiplier(address token);
181 | | error EmptyDataStreamMultiplier(address token);
182 | | error InvalidFeedPrice(address token, int256 price);
183 | | error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);
184 | | error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);
185 | | error InvalidGmOraclePrice(address token);
186 | | error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);
187 | | error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);
188 | | error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);
189 | | error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);
190 | | error EmptyChainlinkPriceFeed(address token);
191 | | error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);
192 | | error MaxRefPriceDeviationExceeded(
193 | | address token,
194 | | uint256 price,
195 | | uint256 refPrice,
196 | | uint256 maxRefPriceDeviationFactor
197 | | );
198 | | error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);
199 | | error EmptyChainlinkPaymentToken();
200 | | error NonAtomicOracleProvider(address provider);
201 | |
202 | | // OracleModule errors
203 | | error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);
204 | | error EndOfOracleSimulation();
205 | |
206 | | // OracleUtils errors
207 | | error InvalidGmSignature(address recoveredSigner, address expectedSigner);
208 | |
209 | | error EmptyPrimaryPrice(address token);
210 | |
211 | | error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);
212 | | error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);
213 | |
214 | | // BaseOrderUtils errors
215 | | error EmptyOrder();
216 | | error UnsupportedOrderType(uint256 orderType);
217 | | error InvalidOrderPrices(
218 | | uint256 primaryPriceMin,
219 | | uint256 primaryPriceMax,
220 | | uint256 triggerPrice,
221 | | uint256 orderType
222 | | );
223 | | error EmptySizeDeltaInTokens();
224 | | error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);
225 | | error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);
226 | | error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);
227 | |
228 | | // IncreaseOrderUtils errors
229 | | error UnexpectedPositionState();
230 | |
231 | | // OrderUtils errors
232 | | error OrderTypeCannotBeCreated(uint256 orderType);
233 | | error OrderAlreadyFrozen();
234 | | error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);
235 | |
236 | | // OrderStoreUtils errors
237 | | error OrderNotFound(bytes32 key);
238 | |
239 | | // SwapOrderUtils errors
240 | | error UnexpectedMarket();
241 | |
242 | | // DecreasePositionCollateralUtils errors
243 | | error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);
244 | | error InvalidOutputToken(address tokenOut, address expectedTokenOut);
245 | |
246 | | // DecreasePositionUtils errors
247 | | error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);
248 | | error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);
249 | | error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);
250 | | error PositionShouldNotBeLiquidated(
251 | | string reason,
252 | | int256 remainingCollateralUsd,
253 | | int256 minCollateralUsd,
254 | | int256 minCollateralUsdForLeverage
255 | | );
256 | |
257 | | // IncreasePositionUtils errors
258 | | error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);
259 | | error InsufficientCollateralUsd(int256 remainingCollateralUsd);
260 | |
261 | | // PositionStoreUtils errors
262 | | error PositionNotFound(bytes32 key);
263 | |
264 | | // PositionUtils errors
265 | | error LiquidatablePosition(
266 | | string reason,
267 | | int256 remainingCollateralUsd,
268 | | int256 minCollateralUsd,
269 | | int256 minCollateralUsdForLeverage
270 | | );
271 | |
272 | | error EmptyPosition();
273 | | error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);
274 | | error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);
275 | |
276 | | // PositionPricingUtils errors
277 | | error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);
278 | | error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);
279 | |
280 | | // ShiftStoreUtils errors
281 | | error ShiftNotFound(bytes32 key);
282 | |
283 | | // ShiftUtils errors
284 | | error EmptyShift();
285 | | error EmptyShiftAmount();
286 | | error ShiftFromAndToMarketAreEqual(address market);
287 | | error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);
288 | | error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);
289 | |
290 | | // SwapPricingUtils errors
291 | | error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);
292 | |
293 | | // RoleModule errors
294 | | error Unauthorized(address msgSender, string role);
295 | |
296 | | // RoleStore errors
297 | | error ThereMustBeAtLeastOneRoleAdmin();
298 | | error ThereMustBeAtLeastOneTimelockMultiSig();
299 | |
300 | | // ExchangeRouter errors
301 | | error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);
302 | | error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);
303 | | error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);
304 | | error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);
305 | |
306 | | // SwapUtils errors
307 | | error InvalidTokenIn(address tokenIn, address market);
308 | | error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);
309 | | error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);
310 | | error DuplicatedMarketInSwapPath(address market);
311 | | error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);
312 | |
313 | | // SubaccountRouter errors
314 | | error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);
315 | |
316 | | // SubaccountUtils errors
317 | | error SubaccountNotAuthorized(address account, address subaccount);
318 | | error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);
319 | |
320 | | // TokenUtils errors
321 | | error EmptyTokenTranferGasLimit(address token);
322 | | error TokenTransferError(address token, address receiver, uint256 amount);
323 | | error EmptyHoldingAddress();
324 | |
325 | | // AccountUtils errors
326 | | error EmptyAccount();
327 | | error EmptyReceiver();
328 | |
329 | | // Array errors
330 | | error CompactedArrayOutOfBounds(
331 | | uint256[] compactedValues,
332 | | uint256 index,
333 | | uint256 slotIndex,
334 | | string label
335 | | );
336 | |
337 | | error ArrayOutOfBoundsUint256(
338 | | uint256[] values,
339 | | uint256 index,
340 | | string label
341 | | );
342 | |
343 | | error ArrayOutOfBoundsBytes(
344 | | bytes[] values,
345 | | uint256 index,
346 | | string label
347 | | );
348 | |
349 | | // WithdrawalHandler errors
350 | | error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);
351 | |
352 | | // WithdrawalStoreUtils errors
353 | | error WithdrawalNotFound(bytes32 key);
354 | |
355 | | // WithdrawalUtils errors
356 | | error EmptyWithdrawal();
357 | | error EmptyWithdrawalAmount();
358 | | error MinLongTokens(uint256 received, uint256 expected);
359 | | error MinShortTokens(uint256 received, uint256 expected);
360 | | error InsufficientMarketTokens(uint256 balance, uint256 expected);
361 | | error InsufficientWntAmount(uint256 wntAmount, uint256 executionFee);
362 | | error InvalidPoolValueForWithdrawal(int256 poolValue);
363 | |
364 | | // Uint256Mask errors
365 | | error MaskIndexOutOfBounds(uint256 index, string label);
366 | | error DuplicatedIndex(uint256 index, string label);
367 | | }
368 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/event/EventEmitter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../role/RoleModule.sol";
6 | | import "./EventUtils.sol";
7 | |
8 | | // @title EventEmitter
9 | | // @dev Contract to emit events
10 | | // This allows main events to be emitted from a single contract
11 | | // Logic contracts can be updated while re-using the same eventEmitter contract
12 | | // Peripheral services like monitoring or analytics would be able to continue
13 | | // to work without an update and without segregating historical data
14 | * | contract EventEmitter is RoleModule {
15 | | event EventLog(
16 | | address msgSender,
17 | | string eventName,
18 | | string indexed eventNameHash,
19 | | EventUtils.EventLogData eventData
20 | | );
21 | |
22 | | event EventLog1(
23 | | address msgSender,
24 | | string eventName,
25 | | string indexed eventNameHash,
26 | | bytes32 indexed topic1,
27 | | EventUtils.EventLogData eventData
28 | | );
29 | |
30 | | event EventLog2(
31 | | address msgSender,
32 | | string eventName,
33 | | string indexed eventNameHash,
34 | | bytes32 indexed topic1,
35 | | bytes32 indexed topic2,
36 | | EventUtils.EventLogData eventData
37 | | );
38 | |
39 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
40 | |
41 | | // @dev emit a general event log
42 | | // @param eventName the name of the event
43 | | // @param eventData the event data
44 | * | function emitEventLog(
45 | | string memory eventName,
46 | | EventUtils.EventLogData memory eventData
47 | | ) external onlyController {
48 | * | emit EventLog(
49 | * | msg.sender,
50 | * | eventName,
51 | * | eventName,
52 | * | eventData
53 | | );
54 | | }
55 | |
56 | | // @dev emit a general event log
57 | | // @param eventName the name of the event
58 | | // @param topic1 topic1 for indexing
59 | | // @param eventData the event data
60 | * | function emitEventLog1(
61 | | string memory eventName,
62 | | bytes32 topic1,
63 | | EventUtils.EventLogData memory eventData
64 | | ) external onlyController {
65 | * | emit EventLog1(
66 | * | msg.sender,
67 | * | eventName,
68 | * | eventName,
69 | * | topic1,
70 | * | eventData
71 | | );
72 | | }
73 | |
74 | | // @dev emit a general event log
75 | | // @param eventName the name of the event
76 | | // @param topic1 topic1 for indexing
77 | | // @param topic2 topic2 for indexing
78 | | // @param eventData the event data
79 | * | function emitEventLog2(
80 | | string memory eventName,
81 | | bytes32 topic1,
82 | | bytes32 topic2,
83 | | EventUtils.EventLogData memory eventData
84 | | ) external onlyController {
85 | * | emit EventLog2(
86 | * | msg.sender,
87 | * | eventName,
88 | * | eventName,
89 | * | topic1,
90 | * | topic2,
91 | * | eventData
92 | | );
93 | | }
94 | | // @dev event log for general use
95 | | // @param topic1 event topic 1
96 | | // @param data additional data
97 | | function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {
98 | | uint256 len = data.length;
99 | | assembly {
100 | | log1(add(data, 32), len, topic1)
101 | | }
102 | | }
103 | |
104 | | // @dev event log for general use
105 | | // @param topic1 event topic 1
106 | | // @param topic2 event topic 2
107 | | // @param data additional data
108 | | function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {
109 | | uint256 len = data.length;
110 | | assembly {
111 | | log2(add(data, 32), len, topic1, topic2)
112 | | }
113 | | }
114 | |
115 | | // @dev event log for general use
116 | | // @param topic1 event topic 1
117 | | // @param topic2 event topic 2
118 | | // @param topic3 event topic 3
119 | | // @param data additional data
120 | | function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {
121 | | uint256 len = data.length;
122 | | assembly {
123 | | log3(add(data, 32), len, topic1, topic2, topic3)
124 | | }
125 | | }
126 | |
127 | | // @dev event log for general use
128 | | // @param topic1 event topic 1
129 | | // @param topic2 event topic 2
130 | | // @param topic3 event topic 3
131 | | // @param topic4 event topic 4
132 | | // @param data additional data
133 | | function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {
134 | | uint256 len = data.length;
135 | | assembly {
136 | | log4(add(data, 32), len, topic1, topic2, topic3, topic4)
137 | | }
138 | | }
139 | | }
140 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/event/EventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | * | library EventUtils {
6 | | struct EmitPositionDecreaseParams {
7 | | bytes32 key;
8 | | address account;
9 | | address market;
10 | | address collateralToken;
11 | | bool isLong;
12 | | }
13 | |
14 | | struct EventLogData {
15 | | AddressItems addressItems;
16 | | UintItems uintItems;
17 | | IntItems intItems;
18 | | BoolItems boolItems;
19 | | Bytes32Items bytes32Items;
20 | | BytesItems bytesItems;
21 | | StringItems stringItems;
22 | | }
23 | |
24 | | struct AddressItems {
25 | | AddressKeyValue[] items;
26 | | AddressArrayKeyValue[] arrayItems;
27 | | }
28 | |
29 | | struct UintItems {
30 | | UintKeyValue[] items;
31 | | UintArrayKeyValue[] arrayItems;
32 | | }
33 | |
34 | | struct IntItems {
35 | | IntKeyValue[] items;
36 | | IntArrayKeyValue[] arrayItems;
37 | | }
38 | |
39 | | struct BoolItems {
40 | | BoolKeyValue[] items;
41 | | BoolArrayKeyValue[] arrayItems;
42 | | }
43 | |
44 | | struct Bytes32Items {
45 | | Bytes32KeyValue[] items;
46 | | Bytes32ArrayKeyValue[] arrayItems;
47 | | }
48 | |
49 | | struct BytesItems {
50 | | BytesKeyValue[] items;
51 | | BytesArrayKeyValue[] arrayItems;
52 | | }
53 | |
54 | | struct StringItems {
55 | | StringKeyValue[] items;
56 | | StringArrayKeyValue[] arrayItems;
57 | | }
58 | |
59 | | struct AddressKeyValue {
60 | | string key;
61 | | address value;
62 | | }
63 | |
64 | | struct AddressArrayKeyValue {
65 | | string key;
66 | | address[] value;
67 | | }
68 | |
69 | | struct UintKeyValue {
70 | | string key;
71 | | uint256 value;
72 | | }
73 | |
74 | | struct UintArrayKeyValue {
75 | | string key;
76 | | uint256[] value;
77 | | }
78 | |
79 | | struct IntKeyValue {
80 | | string key;
81 | | int256 value;
82 | | }
83 | |
84 | | struct IntArrayKeyValue {
85 | | string key;
86 | | int256[] value;
87 | | }
88 | |
89 | | struct BoolKeyValue {
90 | | string key;
91 | | bool value;
92 | | }
93 | |
94 | | struct BoolArrayKeyValue {
95 | | string key;
96 | | bool[] value;
97 | | }
98 | |
99 | | struct Bytes32KeyValue {
100 | | string key;
101 | | bytes32 value;
102 | | }
103 | |
104 | | struct Bytes32ArrayKeyValue {
105 | | string key;
106 | | bytes32[] value;
107 | | }
108 | |
109 | | struct BytesKeyValue {
110 | | string key;
111 | | bytes value;
112 | | }
113 | |
114 | | struct BytesArrayKeyValue {
115 | | string key;
116 | | bytes[] value;
117 | | }
118 | |
119 | | struct StringKeyValue {
120 | | string key;
121 | | string value;
122 | | }
123 | |
124 | | struct StringArrayKeyValue {
125 | | string key;
126 | | string[] value;
127 | | }
128 | |
129 | * | function initItems(AddressItems memory items, uint256 size) internal pure {
130 | * | items.items = new EventUtils.AddressKeyValue[](size);
131 | | }
132 | |
133 | * | function initArrayItems(AddressItems memory items, uint256 size) internal pure {
134 | * | items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);
135 | | }
136 | |
137 | * | function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {
138 | * | items.items[index].key = key;
139 | * | items.items[index].value = value;
140 | | }
141 | |
142 | * | function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {
143 | * | items.arrayItems[index].key = key;
144 | * | items.arrayItems[index].value = value;
145 | | }
146 | |
147 | * | function initItems(UintItems memory items, uint256 size) internal pure {
148 | * | items.items = new EventUtils.UintKeyValue[](size);
149 | | }
150 | |
151 | | function initArrayItems(UintItems memory items, uint256 size) internal pure {
152 | | items.arrayItems = new EventUtils.UintArrayKeyValue[](size);
153 | | }
154 | |
155 | * | function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {
156 | * | items.items[index].key = key;
157 | * | items.items[index].value = value;
158 | | }
159 | |
160 | | function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {
161 | | items.arrayItems[index].key = key;
162 | | items.arrayItems[index].value = value;
163 | | }
164 | |
165 | * | function initItems(IntItems memory items, uint256 size) internal pure {
166 | * | items.items = new EventUtils.IntKeyValue[](size);
167 | | }
168 | |
169 | | function initArrayItems(IntItems memory items, uint256 size) internal pure {
170 | | items.arrayItems = new EventUtils.IntArrayKeyValue[](size);
171 | | }
172 | |
173 | * | function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {
174 | * | items.items[index].key = key;
175 | * | items.items[index].value = value;
176 | | }
177 | |
178 | | function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {
179 | | items.arrayItems[index].key = key;
180 | | items.arrayItems[index].value = value;
181 | | }
182 | |
183 | * | function initItems(BoolItems memory items, uint256 size) internal pure {
184 | * | items.items = new EventUtils.BoolKeyValue[](size);
185 | | }
186 | |
187 | | function initArrayItems(BoolItems memory items, uint256 size) internal pure {
188 | | items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);
189 | | }
190 | |
191 | * | function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {
192 | * | items.items[index].key = key;
193 | * | items.items[index].value = value;
194 | | }
195 | |
196 | | function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {
197 | | items.arrayItems[index].key = key;
198 | | items.arrayItems[index].value = value;
199 | | }
200 | |
201 | * | function initItems(Bytes32Items memory items, uint256 size) internal pure {
202 | * | items.items = new EventUtils.Bytes32KeyValue[](size);
203 | | }
204 | |
205 | | function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {
206 | | items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);
207 | | }
208 | |
209 | * | function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {
210 | * | items.items[index].key = key;
211 | * | items.items[index].value = value;
212 | | }
213 | |
214 | | function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {
215 | | items.arrayItems[index].key = key;
216 | | items.arrayItems[index].value = value;
217 | | }
218 | |
219 | * | function initItems(BytesItems memory items, uint256 size) internal pure {
220 | * | items.items = new EventUtils.BytesKeyValue[](size);
221 | | }
222 | |
223 | | function initArrayItems(BytesItems memory items, uint256 size) internal pure {
224 | | items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);
225 | | }
226 | |
227 | * | function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {
228 | * | items.items[index].key = key;
229 | * | items.items[index].value = value;
230 | | }
231 | |
232 | | function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {
233 | | items.arrayItems[index].key = key;
234 | | items.arrayItems[index].value = value;
235 | | }
236 | |
237 | * | function initItems(StringItems memory items, uint256 size) internal pure {
238 | * | items.items = new EventUtils.StringKeyValue[](size);
239 | | }
240 | |
241 | | function initArrayItems(StringItems memory items, uint256 size) internal pure {
242 | | items.arrayItems = new EventUtils.StringArrayKeyValue[](size);
243 | | }
244 | |
245 | * | function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {
246 | * | items.items[index].key = key;
247 | * | items.items[index].value = value;
248 | | }
249 | |
250 | | function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {
251 | | items.arrayItems[index].key = key;
252 | | items.arrayItems[index].value = value;
253 | | }
254 | | }
255 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/AdlHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderHandler.sol";
6 | |
7 | | // @title AdlHandler
8 | | // @dev Contract to handle adls
9 | * | contract AdlHandler is BaseOrderHandler {
10 | | using SafeCast for uint256;
11 | | using SafeCast for int256;
12 | | using Order for Order.Props;
13 | | using Array for uint256[];
14 | |
15 | | // @dev ExecuteAdlCache struct used in executeAdl to avoid
16 | | // stack too deep errors
17 | | struct ExecuteAdlCache {
18 | | uint256 startingGas;
19 | | bytes32 key;
20 | | bool shouldAllowAdl;
21 | | uint256 maxPnlFactorForAdl;
22 | | int256 pnlToPoolFactor;
23 | | int256 nextPnlToPoolFactor;
24 | | uint256 minPnlFactorForAdl;
25 | | }
26 | |
27 | | constructor(
28 | | RoleStore _roleStore,
29 | | DataStore _dataStore,
30 | | EventEmitter _eventEmitter,
31 | | Oracle _oracle,
32 | | OrderVault _orderVault,
33 | | SwapHandler _swapHandler,
34 | | IReferralStorage _referralStorage
35 | | ) BaseOrderHandler(
36 | | _roleStore,
37 | | _dataStore,
38 | | _eventEmitter,
39 | | _oracle,
40 | | _orderVault,
41 | | _swapHandler,
42 | | _referralStorage
43 | | ) {}
44 | |
45 | | // @dev checks the ADL state to update the isAdlEnabled flag
46 | | // @param market the market to check
47 | | // @param isLong whether to check the long or short side
48 | | // @param oracleParams OracleUtils.SetPricesParams
49 | * | function updateAdlState(
50 | | address market,
51 | | bool isLong,
52 | | OracleUtils.SetPricesParams calldata oracleParams
53 | | ) external
54 | | globalNonReentrant
55 | | onlyAdlKeeper
56 | * | withOraclePrices(oracleParams)
57 | | {
58 | * | AdlUtils.updateAdlState(
59 | * | dataStore,
60 | * | eventEmitter,
61 | * | oracle,
62 | * | market,
63 | * | isLong
64 | | );
65 | | }
66 | |
67 | | // @dev auto-deleverages a position
68 | | // there is no validation that ADL is executed in order of position profit
69 | | // or position size, this is due to the limitation of the gas overhead
70 | | // required to check this ordering
71 | | //
72 | | // ADL keepers could be separately incentivised using a rebate based on
73 | | // position profit, this is not implemented within the contracts at the moment
74 | | //
75 | | // @param account the position's account
76 | | // @param market the position's market
77 | | // @param collateralToken the position's collateralToken
78 | | // @param isLong whether the position is long or short
79 | | // @param sizeDeltaUsd the size to reduce the position by
80 | | // @param oracleParams OracleUtils.SetPricesParams
81 | * | function executeAdl(
82 | | address account,
83 | | address market,
84 | | address collateralToken,
85 | | bool isLong,
86 | | uint256 sizeDeltaUsd,
87 | | OracleUtils.SetPricesParams calldata oracleParams
88 | | ) external
89 | | globalNonReentrant
90 | | onlyAdlKeeper
91 | * | withOraclePrices(oracleParams)
92 | * | {
93 | * | ExecuteAdlCache memory cache;
94 | |
95 | * | cache.startingGas = gasleft();
96 | |
97 | * | AdlUtils.validateAdl(
98 | * | dataStore,
99 | * | oracle,
100 | * | market,
101 | * | isLong
102 | | );
103 | |
104 | * | (cache.shouldAllowAdl, cache.pnlToPoolFactor, cache.maxPnlFactorForAdl) = MarketUtils.isPnlFactorExceeded(
105 | * | dataStore,
106 | * | oracle,
107 | * | market,
108 | * | isLong,
109 | | Keys.MAX_PNL_FACTOR_FOR_ADL
110 | | );
111 | |
112 | * | if (!cache.shouldAllowAdl) {
113 | | revert Errors.AdlNotRequired(cache.pnlToPoolFactor, cache.maxPnlFactorForAdl);
114 | | }
115 | |
116 | * | cache.key = AdlUtils.createAdlOrder(
117 | * | AdlUtils.CreateAdlOrderParams(
118 | * | dataStore,
119 | * | eventEmitter,
120 | * | account,
121 | * | market,
122 | * | collateralToken,
123 | * | isLong,
124 | * | sizeDeltaUsd,
125 | * | Chain.currentBlockNumber(), // updatedAtBlock
126 | * | oracle.minTimestamp() // updatedAtTime
127 | | )
128 | | );
129 | |
130 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, cache.key);
131 | |
132 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(
133 | * | cache.key,
134 | * | order,
135 | * | msg.sender,
136 | * | cache.startingGas,
137 | * | Order.SecondaryOrderType.Adl
138 | | );
139 | |
140 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeAdlFeatureDisabledKey(address(this), uint256(params.order.orderType())));
141 | |
142 | * | ExecuteOrderUtils.executeOrder(params);
143 | |
144 | | // validate that the ratio of pending pnl to pool value was decreased
145 | * | cache.nextPnlToPoolFactor = MarketUtils.getPnlToPoolFactor(dataStore, oracle, market, isLong, true);
146 | * | if (cache.nextPnlToPoolFactor >= cache.pnlToPoolFactor) {
147 | | revert Errors.InvalidAdl(cache.nextPnlToPoolFactor, cache.pnlToPoolFactor);
148 | | }
149 | |
150 | * | cache.minPnlFactorForAdl = MarketUtils.getMinPnlFactorAfterAdl(dataStore, market, isLong);
151 | |
152 | * | if (cache.nextPnlToPoolFactor < cache.minPnlFactorForAdl.toInt256()) {
153 | | revert Errors.PnlOvercorrected(cache.nextPnlToPoolFactor, cache.minPnlFactorForAdl);
154 | | }
155 | | }
156 | | }
157 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/BaseHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../feature/FeatureUtils.sol";
6 | | import "../event/EventEmitter.sol";
7 | | import "../oracle/Oracle.sol";
8 | | import "../oracle/OracleModule.sol";
9 | | import "../role/RoleModule.sol";
10 | | import "../utils/GlobalReentrancyGuard.sol";
11 | |
12 | | contract BaseHandler is RoleModule, GlobalReentrancyGuard, OracleModule {
13 | | EventEmitter public immutable eventEmitter;
14 | |
15 | | constructor(
16 | | RoleStore _roleStore,
17 | | DataStore _dataStore,
18 | | EventEmitter _eventEmitter,
19 | | Oracle _oracle
20 | | ) RoleModule(_roleStore) GlobalReentrancyGuard(_dataStore) OracleModule(_oracle) {
21 | | eventEmitter = _eventEmitter;
22 | | }
23 | |
24 | * | receive() external payable {
25 | * | address wnt = dataStore.getAddress(Keys.WNT);
26 | * | if (msg.sender != wnt) {
27 | | revert Errors.InvalidNativeTokenSender(msg.sender);
28 | | }
29 | | }
30 | |
31 | * | function validateRequestCancellation(
32 | | uint256 createdAtTime,
33 | | string memory requestType
34 | * | ) internal view {
35 | * | uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
36 | * | uint256 requestAge = Chain.currentTimestamp() - createdAtTime;
37 | * | if (requestAge < requestExpirationTime) {
38 | * | revert Errors.RequestNotYetCancellable(requestAge, requestExpirationTime, requestType);
39 | | }
40 | | }
41 | | }
42 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/BaseOrderHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseHandler.sol";
6 | | import "../callback/CallbackUtils.sol";
7 | |
8 | | import "../adl/AdlUtils.sol";
9 | | import "../liquidation/LiquidationUtils.sol";
10 | |
11 | | import "../market/Market.sol";
12 | | import "../market/MarketToken.sol";
13 | |
14 | | import "../order/Order.sol";
15 | | import "../order/OrderVault.sol";
16 | | import "../order/OrderUtils.sol";
17 | | import "../order/ExecuteOrderUtils.sol";
18 | |
19 | | import "../referral/IReferralStorage.sol";
20 | |
21 | | // @title BaseOrderHandler
22 | | // @dev Base contract for shared order handler functions
23 | | contract BaseOrderHandler is BaseHandler {
24 | | using SafeCast for uint256;
25 | | using Order for Order.Props;
26 | | using Array for uint256[];
27 | |
28 | | OrderVault public immutable orderVault;
29 | | SwapHandler public immutable swapHandler;
30 | | IReferralStorage public immutable referralStorage;
31 | |
32 | | constructor(
33 | | RoleStore _roleStore,
34 | | DataStore _dataStore,
35 | | EventEmitter _eventEmitter,
36 | | Oracle _oracle,
37 | | OrderVault _orderVault,
38 | | SwapHandler _swapHandler,
39 | | IReferralStorage _referralStorage
40 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {
41 | | orderVault = _orderVault;
42 | | swapHandler = _swapHandler;
43 | | referralStorage = _referralStorage;
44 | | }
45 | |
46 | | // @dev get the BaseOrderUtils.ExecuteOrderParams to execute an order
47 | | // @return the required BaseOrderUtils.ExecuteOrderParams params to execute the order
48 | * | function _getExecuteOrderParams(
49 | | bytes32 key,
50 | | Order.Props memory order,
51 | | address keeper,
52 | | uint256 startingGas,
53 | | Order.SecondaryOrderType secondaryOrderType
54 | * | ) internal view returns (BaseOrderUtils.ExecuteOrderParams memory) {
55 | * | BaseOrderUtils.ExecuteOrderParams memory params;
56 | |
57 | * | params.key = key;
58 | * | params.order = order;
59 | * | params.swapPathMarkets = MarketUtils.getSwapPathMarkets(
60 | * | dataStore,
61 | * | params.order.swapPath()
62 | | );
63 | |
64 | * | params.contracts.dataStore = dataStore;
65 | * | params.contracts.eventEmitter = eventEmitter;
66 | * | params.contracts.orderVault = orderVault;
67 | * | params.contracts.oracle = oracle;
68 | * | params.contracts.swapHandler = swapHandler;
69 | * | params.contracts.referralStorage = referralStorage;
70 | |
71 | * | params.minOracleTimestamp = oracle.minTimestamp();
72 | * | params.maxOracleTimestamp = oracle.maxTimestamp();
73 | |
74 | * | if (params.order.market() != address(0)) {
75 | * | params.market = MarketUtils.getEnabledMarket(params.contracts.dataStore, params.order.market());
76 | | }
77 | |
78 | * | params.keeper = keeper;
79 | * | params.startingGas = startingGas;
80 | |
81 | * | params.secondaryOrderType = secondaryOrderType;
82 | |
83 | * | return params;
84 | | }
85 | | }
86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/DepositHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseHandler.sol";
6 | |
7 | | import "../market/Market.sol";
8 | | import "../market/MarketToken.sol";
9 | |
10 | | import "../deposit/Deposit.sol";
11 | | import "../deposit/DepositVault.sol";
12 | | import "../deposit/DepositUtils.sol";
13 | | import "../deposit/ExecuteDepositUtils.sol";
14 | |
15 | | import "./IDepositHandler.sol";
16 | |
17 | | // @title DepositHandler
18 | | // @dev Contract to handle creation, execution and cancellation of deposits
19 | * | contract DepositHandler is IDepositHandler, BaseHandler {
20 | | using Deposit for Deposit.Props;
21 | |
22 | | DepositVault public immutable depositVault;
23 | |
24 | | constructor(
25 | | RoleStore _roleStore,
26 | | DataStore _dataStore,
27 | | EventEmitter _eventEmitter,
28 | | Oracle _oracle,
29 | | DepositVault _depositVault
30 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {
31 | | depositVault = _depositVault;
32 | | }
33 | |
34 | | // @dev creates a deposit in the deposit store
35 | | // @param account the depositing account
36 | | // @param params DepositUtils.CreateDepositParams
37 | * | function createDeposit(
38 | | address account,
39 | | DepositUtils.CreateDepositParams calldata params
40 | * | ) external override globalNonReentrant onlyController returns (bytes32) {
41 | * | FeatureUtils.validateFeature(dataStore, Keys.createDepositFeatureDisabledKey(address(this)));
42 | |
43 | * | return DepositUtils.createDeposit(
44 | * | dataStore,
45 | * | eventEmitter,
46 | * | depositVault,
47 | * | account,
48 | * | params
49 | | );
50 | | }
51 | |
52 | | // @dev cancels a deposit
53 | | // @param key the deposit key
54 | * | function cancelDeposit(bytes32 key) external override globalNonReentrant onlyController {
55 | * | uint256 startingGas = gasleft();
56 | |
57 | * | DataStore _dataStore = dataStore;
58 | * | Deposit.Props memory deposit = DepositStoreUtils.get(_dataStore, key);
59 | |
60 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelDepositFeatureDisabledKey(address(this)));
61 | |
62 | * | validateRequestCancellation(
63 | * | deposit.updatedAtTime(),
64 | | "Deposit"
65 | | );
66 | |
67 | * | DepositUtils.cancelDeposit(
68 | * | _dataStore,
69 | * | eventEmitter,
70 | * | depositVault,
71 | * | key,
72 | * | deposit.account(),
73 | * | startingGas,
74 | * | Keys.USER_INITIATED_CANCEL,
75 | | ""
76 | | );
77 | | }
78 | |
79 | | // @dev executes a deposit
80 | | // @param key the key of the deposit to execute
81 | | // @param oracleParams OracleUtils.SetPricesParams
82 | * | function executeDeposit(
83 | | bytes32 key,
84 | | OracleUtils.SetPricesParams calldata oracleParams
85 | | ) external
86 | | globalNonReentrant
87 | | onlyOrderKeeper
88 | * | withOraclePrices(oracleParams)
89 | * | {
90 | * | uint256 startingGas = gasleft();
91 | |
92 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);
93 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit);
94 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);
95 | |
96 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);
97 | |
98 | * | try this._executeDeposit{ gas: executionGas }(
99 | * | key,
100 | * | deposit,
101 | * | msg.sender
102 | | ) {
103 | * | } catch (bytes memory reasonBytes) {
104 | * | _handleDepositError(
105 | * | key,
106 | * | startingGas,
107 | * | reasonBytes
108 | | );
109 | | }
110 | | }
111 | |
112 | | // @dev simulate execution of a deposit to check for any errors
113 | | // @param key the deposit key
114 | | // @param params OracleUtils.SimulatePricesParams
115 | | function simulateExecuteDeposit(
116 | | bytes32 key,
117 | | OracleUtils.SimulatePricesParams memory params
118 | | ) external
119 | | override
120 | | onlyController
121 | | withSimulatedOraclePrices(params)
122 | | globalNonReentrant
123 | | {
124 | | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);
125 | |
126 | | this._executeDeposit(
127 | | key,
128 | | deposit,
129 | | msg.sender
130 | | );
131 | | }
132 | |
133 | | // @dev executes a deposit
134 | | // @param oracleParams OracleUtils.SetPricesParams
135 | | // @param keeper the keeper executing the deposit
136 | | // @param startingGas the starting gas
137 | * | function _executeDeposit(
138 | | bytes32 key,
139 | | Deposit.Props memory deposit,
140 | | address keeper
141 | * | ) external onlySelf {
142 | * | uint256 startingGas = gasleft();
143 | |
144 | * | FeatureUtils.validateFeature(dataStore, Keys.executeDepositFeatureDisabledKey(address(this)));
145 | |
146 | * | ExecuteDepositUtils.ExecuteDepositParams memory params = ExecuteDepositUtils.ExecuteDepositParams(
147 | * | dataStore,
148 | * | eventEmitter,
149 | * | depositVault,
150 | * | oracle,
151 | * | key,
152 | * | keeper,
153 | * | startingGas,
154 | * | ISwapPricingUtils.SwapPricingType.TwoStep,
155 | * | true // includeVirtualInventoryImpact
156 | | );
157 | |
158 | * | ExecuteDepositUtils.executeDeposit(params, deposit);
159 | | }
160 | |
161 | | // @dev handle errors from deposits
162 | | // @param key the deposit key
163 | | // @param startingGas the starting gas of the txn
164 | | // @param reasonBytes the reason bytes of the error
165 | * | function _handleDepositError(
166 | | bytes32 key,
167 | | uint256 startingGas,
168 | | bytes memory reasonBytes
169 | * | ) internal {
170 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);
171 | |
172 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);
173 | |
174 | * | if (
175 | * | OracleUtils.isOracleError(errorSelector) ||
176 | * | errorSelector == Errors.DisabledFeature.selector ||
177 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector
178 | | ) {
179 | * | ErrorUtils.revertWithCustomError(reasonBytes);
180 | | }
181 | |
182 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
183 | |
184 | * | DepositUtils.cancelDeposit(
185 | * | dataStore,
186 | * | eventEmitter,
187 | * | depositVault,
188 | * | key,
189 | * | msg.sender,
190 | * | startingGas,
191 | * | reason,
192 | * | reasonBytes
193 | | );
194 | | }
195 | | }
196 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IDepositHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../deposit/DepositUtils.sol";
6 | | import "../oracle/OracleUtils.sol";
7 | |
8 | | interface IDepositHandler {
9 | | function createDeposit(address account, DepositUtils.CreateDepositParams calldata params) external returns (bytes32);
10 | | function cancelDeposit(bytes32 key) external;
11 | | function simulateExecuteDeposit(
12 | | bytes32 key,
13 | | OracleUtils.SimulatePricesParams memory params
14 | | ) external;
15 | | }
16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IGlvHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../glv/GlvDepositUtils.sol";
6 | | import "../oracle/OracleUtils.sol";
7 | |
8 | | interface IGlvHandler {
9 | | function createGlvDeposit(address account, GlvDepositUtils.CreateGlvDepositParams calldata params) external returns (bytes32);
10 | | function cancelGlvDeposit(bytes32 key) external;
11 | | function simulateExecuteGlvDeposit(
12 | | bytes32 key,
13 | | OracleUtils.SimulatePricesParams memory params
14 | | ) external;
15 | | }
16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IOrderHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../order/IBaseOrderUtils.sol";
6 | | import "../oracle/OracleUtils.sol";
7 | |
8 | | interface IOrderHandler {
9 | | function createOrder(address account, IBaseOrderUtils.CreateOrderParams calldata params) external returns (bytes32);
10 | |
11 | | function simulateExecuteOrder(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;
12 | |
13 | | function updateOrder(
14 | | bytes32 key,
15 | | uint256 sizeDeltaUsd,
16 | | uint256 acceptablePrice,
17 | | uint256 triggerPrice,
18 | | uint256 minOutputAmount,
19 | | bool autoCancel,
20 | | Order.Props memory order
21 | | ) external;
22 | |
23 | | function cancelOrder(bytes32 key) external;
24 | | }
25 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IShiftHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../shift/ShiftUtils.sol";
6 | | import "../oracle/OracleUtils.sol";
7 | |
8 | | interface IShiftHandler {
9 | | function createShift(address account, ShiftUtils.CreateShiftParams calldata params) external returns (bytes32);
10 | | function cancelShift(bytes32 key) external;
11 | | function simulateExecuteShift(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;
12 | | }
13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IWithdrawalHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../withdrawal/WithdrawalUtils.sol";
6 | | import "../oracle/OracleUtils.sol";
7 | | import "../pricing/ISwapPricingUtils.sol";
8 | |
9 | | interface IWithdrawalHandler {
10 | | function createWithdrawal(address account, WithdrawalUtils.CreateWithdrawalParams calldata params) external returns (bytes32);
11 | | function cancelWithdrawal(bytes32 key) external;
12 | | function executeAtomicWithdrawal(
13 | | address account,
14 | | WithdrawalUtils.CreateWithdrawalParams calldata params,
15 | | OracleUtils.SetPricesParams calldata oracleParams
16 | | ) external;
17 | | function simulateExecuteWithdrawal(
18 | | bytes32 key,
19 | | OracleUtils.SimulatePricesParams memory params,
20 | | ISwapPricingUtils.SwapPricingType swapPricingType
21 | | ) external;
22 | | }
23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/LiquidationHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderHandler.sol";
6 | |
7 | | // @title LiquidationHandler
8 | | // @dev Contract to handle liquidations
9 | * | contract LiquidationHandler is BaseOrderHandler {
10 | | using SafeCast for uint256;
11 | | using Order for Order.Props;
12 | | using Array for uint256[];
13 | |
14 | | constructor(
15 | | RoleStore _roleStore,
16 | | DataStore _dataStore,
17 | | EventEmitter _eventEmitter,
18 | | Oracle _oracle,
19 | | OrderVault _orderVault,
20 | | SwapHandler _swapHandler,
21 | | IReferralStorage _referralStorage
22 | | ) BaseOrderHandler(
23 | | _roleStore,
24 | | _dataStore,
25 | | _eventEmitter,
26 | | _oracle,
27 | | _orderVault,
28 | | _swapHandler,
29 | | _referralStorage
30 | | ) {}
31 | |
32 | | // @dev executes a position liquidation
33 | | // @param account the account of the position to liquidate
34 | | // @param market the position's market
35 | | // @param collateralToken the position's collateralToken
36 | | // @param isLong whether the position is long or short
37 | | // @param oracleParams OracleUtils.SetPricesParams
38 | * | function executeLiquidation(
39 | | address account,
40 | | address market,
41 | | address collateralToken,
42 | | bool isLong,
43 | | OracleUtils.SetPricesParams calldata oracleParams
44 | | ) external
45 | | globalNonReentrant
46 | | onlyLiquidationKeeper
47 | * | withOraclePrices(oracleParams)
48 | * | {
49 | * | uint256 startingGas = gasleft();
50 | |
51 | * | oracle.validateSequencerUp();
52 | |
53 | * | bytes32 key = LiquidationUtils.createLiquidationOrder(
54 | * | dataStore,
55 | * | eventEmitter,
56 | * | account,
57 | * | market,
58 | * | collateralToken,
59 | * | isLong
60 | | );
61 | |
62 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
63 | |
64 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(
65 | * | key,
66 | * | order,
67 | * | msg.sender,
68 | * | startingGas,
69 | * | Order.SecondaryOrderType.None
70 | | );
71 | |
72 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType())));
73 | |
74 | * | ExecuteOrderUtils.executeOrder(params);
75 | | }
76 | | }
77 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/OrderHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderHandler.sol";
6 | | import "../error/ErrorUtils.sol";
7 | | import "./IOrderHandler.sol";
8 | |
9 | | // @title OrderHandler
10 | | // @dev Contract to handle creation, execution and cancellation of orders
11 | * | contract OrderHandler is IOrderHandler, BaseOrderHandler {
12 | | using SafeCast for uint256;
13 | | using Order for Order.Props;
14 | | using Array for uint256[];
15 | |
16 | | constructor(
17 | | RoleStore _roleStore,
18 | | DataStore _dataStore,
19 | | EventEmitter _eventEmitter,
20 | | Oracle _oracle,
21 | | OrderVault _orderVault,
22 | | SwapHandler _swapHandler,
23 | | IReferralStorage _referralStorage
24 | | ) BaseOrderHandler(
25 | | _roleStore,
26 | | _dataStore,
27 | | _eventEmitter,
28 | | _oracle,
29 | | _orderVault,
30 | | _swapHandler,
31 | | _referralStorage
32 | | ) {}
33 | |
34 | | // @dev creates an order in the order store
35 | | // @param account the order's account
36 | | // @param params BaseOrderUtils.CreateOrderParams
37 | * | function createOrder(
38 | | address account,
39 | | IBaseOrderUtils.CreateOrderParams calldata params
40 | * | ) external override globalNonReentrant onlyController returns (bytes32) {
41 | * | FeatureUtils.validateFeature(dataStore, Keys.createOrderFeatureDisabledKey(address(this), uint256(params.orderType)));
42 | |
43 | * | return OrderUtils.createOrder(
44 | * | dataStore,
45 | * | eventEmitter,
46 | * | orderVault,
47 | * | referralStorage,
48 | * | account,
49 | * | params
50 | | );
51 | | }
52 | |
53 | | /**
54 | | * @dev Updates the given order with the specified size delta, acceptable price, and trigger price.
55 | | * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner
56 | | * of the order, and the order must not be a market order. The size delta, trigger price, and
57 | | * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is
58 | | * transferred to the contract is added to the order's execution fee. The updated order is then saved
59 | | * in the order store, and an `OrderUpdated` event is emitted.
60 | | *
61 | | * A user may be able to observe exchange prices and prevent order execution by updating the order's
62 | | * trigger price or acceptable price
63 | | *
64 | | * The main front-running concern is if a user knows whether the price is going to move up or down
65 | | * then positions accordingly, e.g. if price is going to move up then the user opens a long position
66 | | *
67 | | * With updating of orders, a user may know that price could be lower and delays the execution of an
68 | | * order by updating it, this should not be a significant front-running concern since it is similar
69 | | * to observing prices then creating a market order as price is decreasing
70 | | *
71 | | * @param key The unique ID of the order to be updated
72 | | * @param sizeDeltaUsd The new size delta for the order
73 | | * @param acceptablePrice The new acceptable price for the order
74 | | * @param triggerPrice The new trigger price for the order
75 | | */
76 | | function updateOrder(
77 | | bytes32 key,
78 | | uint256 sizeDeltaUsd,
79 | | uint256 acceptablePrice,
80 | | uint256 triggerPrice,
81 | | uint256 minOutputAmount,
82 | | bool autoCancel,
83 | | Order.Props memory order
84 | | ) external override globalNonReentrant onlyController {
85 | | FeatureUtils.validateFeature(dataStore, Keys.updateOrderFeatureDisabledKey(address(this), uint256(order.orderType())));
86 | |
87 | | if (BaseOrderUtils.isMarketOrder(order.orderType())) {
88 | | revert Errors.OrderNotUpdatable(uint256(order.orderType()));
89 | | }
90 | |
91 | | order.setSizeDeltaUsd(sizeDeltaUsd);
92 | | order.setTriggerPrice(triggerPrice);
93 | | order.setAcceptablePrice(acceptablePrice);
94 | | order.setMinOutputAmount(minOutputAmount);
95 | | order.setIsFrozen(false);
96 | | order.setAutoCancel(autoCancel);
97 | |
98 | | // allow topping up of executionFee as frozen orders
99 | | // will have their executionFee reduced
100 | | address wnt = TokenUtils.wnt(dataStore);
101 | | uint256 receivedWnt = orderVault.recordTransferIn(wnt);
102 | | order.setExecutionFee(order.executionFee() + receivedWnt);
103 | |
104 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);
105 | | uint256 oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(order.swapPath().length);
106 | | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, order.executionFee(), oraclePriceCount);
107 | |
108 | | order.touch();
109 | |
110 | | BaseOrderUtils.validateNonEmptyOrder(order);
111 | |
112 | | OrderStoreUtils.set(dataStore, key, order);
113 | |
114 | | OrderUtils.updateAutoCancelList(dataStore, key, order, autoCancel);
115 | | OrderUtils.validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order);
116 | |
117 | | OrderEventUtils.emitOrderUpdated(
118 | | eventEmitter,
119 | | key,
120 | | order.account(),
121 | | sizeDeltaUsd,
122 | | acceptablePrice,
123 | | triggerPrice,
124 | | minOutputAmount,
125 | | order.updatedAtTime()
126 | | );
127 | | }
128 | |
129 | | /**
130 | | * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order
131 | | * type. The caller must be the owner of the order. The order is cancelled by calling the `cancelOrder()`
132 | | * function in the `OrderUtils` contract. This function also records the starting gas amount and the
133 | | * reason for cancellation, which is passed to the `cancelOrder()` function.
134 | | *
135 | | * @param key The unique ID of the order to be cancelled
136 | | */
137 | * | function cancelOrder(bytes32 key) external override globalNonReentrant onlyController {
138 | * | uint256 startingGas = gasleft();
139 | |
140 | * | DataStore _dataStore = dataStore;
141 | * | Order.Props memory order = OrderStoreUtils.get(_dataStore, key);
142 | |
143 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelOrderFeatureDisabledKey(address(this), uint256(order.orderType())));
144 | |
145 | * | if (BaseOrderUtils.isMarketOrder(order.orderType())) {
146 | * | validateRequestCancellation(
147 | * | order.updatedAtTime(),
148 | | "Order"
149 | | );
150 | | }
151 | |
152 | * | OrderUtils.cancelOrder(
153 | * | OrderUtils.CancelOrderParams(
154 | * | dataStore,
155 | * | eventEmitter,
156 | * | orderVault,
157 | * | key,
158 | * | order.account(),
159 | * | startingGas,
160 | * | true, // isExternalCall
161 | * | Keys.USER_INITIATED_CANCEL,
162 | | ""
163 | | )
164 | | );
165 | | }
166 | |
167 | | // @dev simulate execution of an order to check for any errors
168 | | // @param key the order key
169 | | // @param params OracleUtils.SimulatePricesParams
170 | | function simulateExecuteOrder(
171 | | bytes32 key,
172 | | OracleUtils.SimulatePricesParams memory params
173 | | ) external
174 | | override
175 | | onlyController
176 | | withSimulatedOraclePrices(params)
177 | | globalNonReentrant
178 | | {
179 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
180 | |
181 | | this._executeOrder(
182 | | key,
183 | | order,
184 | | msg.sender
185 | | );
186 | | }
187 | |
188 | | // @dev executes an order
189 | | // @param key the key of the order to execute
190 | | // @param oracleParams OracleUtils.SetPricesParams
191 | * | function executeOrder(
192 | | bytes32 key,
193 | | OracleUtils.SetPricesParams calldata oracleParams
194 | | ) external
195 | | globalNonReentrant
196 | | onlyOrderKeeper
197 | * | withOraclePrices(oracleParams)
198 | * | {
199 | * | uint256 startingGas = gasleft();
200 | |
201 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
202 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);
203 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);
204 | |
205 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);
206 | |
207 | * | try this._executeOrder{ gas: executionGas }(
208 | * | key,
209 | * | order,
210 | * | msg.sender
211 | | ) {
212 | * | } catch (bytes memory reasonBytes) {
213 | * | _handleOrderError(key, startingGas, reasonBytes);
214 | | }
215 | | }
216 | |
217 | | // @dev executes an order
218 | | // @param key the key of the order to execute
219 | | // @param oracleParams OracleUtils.SetPricesParams
220 | | // @param keeper the keeper executing the order
221 | | // @param startingGas the starting gas
222 | * | function _executeOrder(
223 | | bytes32 key,
224 | | Order.Props memory order,
225 | | address keeper
226 | * | ) external onlySelf {
227 | * | uint256 startingGas = gasleft();
228 | |
229 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams(
230 | * | key,
231 | * | order,
232 | * | keeper,
233 | * | startingGas,
234 | * | Order.SecondaryOrderType.None
235 | | );
236 | | // limit swaps require frozen order keeper for execution since on creation it can fail due to output amount
237 | | // which would automatically cause the order to be frozen
238 | | // limit increase and limit / trigger decrease orders may fail due to output amount as well and become frozen
239 | | // but only if their acceptablePrice is reached
240 | * | if (params.order.isFrozen() || params.order.orderType() == Order.OrderType.LimitSwap) {
241 | * | _validateFrozenOrderKeeper(keeper);
242 | | }
243 | |
244 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType())));
245 | |
246 | * | ExecuteOrderUtils.executeOrder(params);
247 | | }
248 | |
249 | | // @dev handle a caught order error
250 | | // @param key the order's key
251 | | // @param startingGas the starting gas
252 | | // @param reason the error reason
253 | | // @param reasonKey the hash or the error reason
254 | * | function _handleOrderError(
255 | | bytes32 key,
256 | | uint256 startingGas,
257 | | bytes memory reasonBytes
258 | * | ) internal {
259 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);
260 | |
261 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);
262 | |
263 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
264 | * | bool isMarketOrder = BaseOrderUtils.isMarketOrder(order.orderType());
265 | |
266 | * | if (
267 | * | OracleUtils.isOracleError(errorSelector) ||
268 | | // if the order is already frozen, revert with the custom error to provide more information
269 | | // on why the order cannot be executed
270 | * | order.isFrozen() ||
271 | | // for market orders, the EmptyPosition error should still lead to the
272 | | // order being cancelled
273 | | // for limit, trigger orders, the EmptyPosition error should lead to the transaction
274 | | // being reverted instead
275 | | // if the position is created or increased later, the oracle prices used to fulfill the order
276 | | // must be after the position was last increased, this is validated in DecreaseOrderUtils
277 | * | (!isMarketOrder && errorSelector == Errors.EmptyPosition.selector) ||
278 | * | errorSelector == Errors.EmptyOrder.selector ||
279 | | // if the order execution feature is disabled, it may be possible
280 | | // for a user to cancel their orders after the feature is re-enabled
281 | | // or they may be able to execute the order at an outdated price
282 | | // depending on the order keeper
283 | | // disabling of features should be a rare occurrence, it may be
284 | | // preferrable to still execute the orders when the feature is re-enabled
285 | | // instead of cancelling / freezing the orders
286 | | // if features are not frequently disabled, the amount of front-running
287 | | // from this should not be significant
288 | | // based on this it may also be advisable to disable the cancelling of orders
289 | | // if the execution of orders is disabled
290 | * | errorSelector == Errors.DisabledFeature.selector ||
291 | * | errorSelector == Errors.InvalidKeeperForFrozenOrder.selector ||
292 | * | errorSelector == Errors.UnsupportedOrderType.selector ||
293 | | // the transaction is reverted for InvalidOrderPrices since the oracle prices
294 | | // do not fulfill the specified trigger price
295 | * | errorSelector == Errors.InvalidOrderPrices.selector ||
296 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector
297 | | ) {
298 | * | ErrorUtils.revertWithCustomError(reasonBytes);
299 | | }
300 | |
301 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
302 | |
303 | * | if (
304 | * | isMarketOrder ||
305 | * | errorSelector == Errors.InvalidPositionMarket.selector ||
306 | * | errorSelector == Errors.InvalidCollateralTokenForMarket.selector ||
307 | * | errorSelector == Errors.InvalidPositionSizeValues.selector
308 | | ) {
309 | * | OrderUtils.cancelOrder(
310 | * | OrderUtils.CancelOrderParams(
311 | * | dataStore,
312 | * | eventEmitter,
313 | * | orderVault,
314 | * | key,
315 | * | msg.sender,
316 | * | startingGas,
317 | * | true, // isExternalCall
318 | * | reason,
319 | * | reasonBytes
320 | | )
321 | | );
322 | |
323 | * | return;
324 | | }
325 | |
326 | | // freeze unfulfillable orders to prevent the order system from being gamed
327 | | // an example of gaming would be if a user creates a limit order
328 | | // with size greater than the available amount in the pool
329 | | // the user waits for their limit price to be hit, and if price
330 | | // moves in their favour after, they can deposit into the pool
331 | | // to allow the order to be executed then close the order for a profit
332 | | //
333 | | // frozen order keepers are expected to execute orders only if the
334 | | // latest prices match the trigger price
335 | | //
336 | | // a user can also call updateOrder to unfreeze an order
337 | * | OrderUtils.freezeOrder(
338 | * | dataStore,
339 | * | eventEmitter,
340 | * | orderVault,
341 | * | key,
342 | * | msg.sender,
343 | * | startingGas,
344 | * | reason,
345 | * | reasonBytes
346 | | );
347 | | }
348 | |
349 | | // @dev validate that the keeper is a frozen order keeper
350 | | // @param keeper address of the keeper
351 | * | function _validateFrozenOrderKeeper(address keeper) internal view {
352 | * | if (!roleStore.hasRole(keeper, Role.FROZEN_ORDER_KEEPER)) {
353 | | revert Errors.InvalidKeeperForFrozenOrder(keeper);
354 | | }
355 | | }
356 | | }
357 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/ShiftHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseHandler.sol";
6 | | import "../shift/ShiftVault.sol";
7 | | import "../shift/Shift.sol";
8 | | import "../shift/ShiftUtils.sol";
9 | | import "./IShiftHandler.sol";
10 | |
11 | * | contract ShiftHandler is IShiftHandler, BaseHandler {
12 | | using Shift for Shift.Props;
13 | |
14 | | ShiftVault public immutable shiftVault;
15 | |
16 | | constructor(
17 | | RoleStore _roleStore,
18 | | DataStore _dataStore,
19 | | EventEmitter _eventEmitter,
20 | | Oracle _oracle,
21 | | ShiftVault _shiftVault
22 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {
23 | | shiftVault = _shiftVault;
24 | | }
25 | |
26 | | function createShift(
27 | | address account,
28 | | ShiftUtils.CreateShiftParams calldata params
29 | | ) external override globalNonReentrant onlyController returns (bytes32) {
30 | | FeatureUtils.validateFeature(dataStore, Keys.createShiftFeatureDisabledKey(address(this)));
31 | |
32 | | return ShiftUtils.createShift(
33 | | dataStore,
34 | | eventEmitter,
35 | | shiftVault,
36 | | account,
37 | | params
38 | | );
39 | | }
40 | |
41 | | function cancelShift(bytes32 key) external override globalNonReentrant onlyController {
42 | | uint256 startingGas = gasleft();
43 | |
44 | | DataStore _dataStore = dataStore;
45 | | Shift.Props memory shift = ShiftStoreUtils.get(_dataStore, key);
46 | |
47 | | FeatureUtils.validateFeature(_dataStore, Keys.cancelShiftFeatureDisabledKey(address(this)));
48 | |
49 | | validateRequestCancellation(
50 | | shift.updatedAtTime(),
51 | | "Shift"
52 | | );
53 | |
54 | | ShiftUtils.cancelShift(
55 | | _dataStore,
56 | | eventEmitter,
57 | | shiftVault,
58 | | key,
59 | | shift.account(),
60 | | startingGas,
61 | | Keys.USER_INITIATED_CANCEL,
62 | | ""
63 | | );
64 | | }
65 | |
66 | | function executeShift(
67 | | bytes32 key,
68 | | OracleUtils.SetPricesParams calldata oracleParams
69 | | ) external
70 | | globalNonReentrant
71 | | onlyOrderKeeper
72 | | withOraclePrices(oracleParams)
73 | | {
74 | | uint256 startingGas = gasleft();
75 | |
76 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);
77 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift);
78 | | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);
79 | |
80 | | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);
81 | |
82 | | try this._executeShift{ gas: executionGas }(
83 | | key,
84 | | shift,
85 | | msg.sender
86 | | ) {
87 | | } catch (bytes memory reasonBytes) {
88 | | _handleShiftError(
89 | | key,
90 | | startingGas,
91 | | reasonBytes
92 | | );
93 | | }
94 | | }
95 | |
96 | | function simulateExecuteShift(
97 | | bytes32 key,
98 | | OracleUtils.SimulatePricesParams memory params
99 | | ) external
100 | | override
101 | | onlyController
102 | | withSimulatedOraclePrices(params)
103 | | globalNonReentrant
104 | | {
105 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);
106 | |
107 | | this._executeShift(
108 | | key,
109 | | shift,
110 | | msg.sender
111 | | );
112 | | }
113 | |
114 | | function _executeShift(
115 | | bytes32 key,
116 | | Shift.Props memory shift,
117 | | address keeper
118 | | ) external onlySelf {
119 | | uint256 startingGas = gasleft();
120 | |
121 | | FeatureUtils.validateFeature(dataStore, Keys.executeShiftFeatureDisabledKey(address(this)));
122 | |
123 | | ShiftUtils.ExecuteShiftParams memory params = ShiftUtils.ExecuteShiftParams(
124 | | dataStore,
125 | | eventEmitter,
126 | | shiftVault,
127 | | oracle,
128 | | key,
129 | | keeper,
130 | | startingGas
131 | | );
132 | |
133 | | ShiftUtils.executeShift(params, shift);
134 | | }
135 | |
136 | | function _handleShiftError(
137 | | bytes32 key,
138 | | uint256 startingGas,
139 | | bytes memory reasonBytes
140 | | ) internal {
141 | | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);
142 | |
143 | | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);
144 | |
145 | | if (
146 | | OracleUtils.isOracleError(errorSelector) ||
147 | | errorSelector == Errors.DisabledFeature.selector
148 | | ) {
149 | | ErrorUtils.revertWithCustomError(reasonBytes);
150 | | }
151 | |
152 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
153 | |
154 | | ShiftUtils.cancelShift(
155 | | dataStore,
156 | | eventEmitter,
157 | | shiftVault,
158 | | key,
159 | | msg.sender,
160 | | startingGas,
161 | | reason,
162 | | reasonBytes
163 | | );
164 | | }
165 | | }
166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/WithdrawalHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseHandler.sol";
6 | | import "../error/ErrorUtils.sol";
7 | |
8 | | import "../market/Market.sol";
9 | | import "../market/MarketToken.sol";
10 | |
11 | | import "../withdrawal/Withdrawal.sol";
12 | | import "../withdrawal/WithdrawalVault.sol";
13 | | import "../withdrawal/WithdrawalStoreUtils.sol";
14 | | import "../withdrawal/WithdrawalUtils.sol";
15 | | import "../withdrawal/ExecuteWithdrawalUtils.sol";
16 | |
17 | | import "./IWithdrawalHandler.sol";
18 | |
19 | | // @title WithdrawalHandler
20 | | // @dev Contract to handle creation, execution and cancellation of withdrawals
21 | * | contract WithdrawalHandler is IWithdrawalHandler, BaseHandler {
22 | | using Withdrawal for Withdrawal.Props;
23 | |
24 | | WithdrawalVault public immutable withdrawalVault;
25 | |
26 | | constructor(
27 | | RoleStore _roleStore,
28 | | DataStore _dataStore,
29 | | EventEmitter _eventEmitter,
30 | | Oracle _oracle,
31 | | WithdrawalVault _withdrawalVault
32 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) {
33 | | withdrawalVault = _withdrawalVault;
34 | | }
35 | |
36 | | // @dev creates a withdrawal in the withdrawal store
37 | | // @param account the withdrawing account
38 | | // @param params WithdrawalUtils.CreateWithdrawalParams
39 | * | function createWithdrawal(
40 | | address account,
41 | | WithdrawalUtils.CreateWithdrawalParams calldata params
42 | * | ) external override globalNonReentrant onlyController returns (bytes32) {
43 | * | FeatureUtils.validateFeature(dataStore, Keys.createWithdrawalFeatureDisabledKey(address(this)));
44 | |
45 | * | return WithdrawalUtils.createWithdrawal(
46 | * | dataStore,
47 | * | eventEmitter,
48 | * | withdrawalVault,
49 | * | account,
50 | * | params
51 | | );
52 | | }
53 | |
54 | | // @dev cancels a withdrawal
55 | | // @param key the withdrawal key
56 | * | function cancelWithdrawal(bytes32 key) external override globalNonReentrant onlyController {
57 | * | uint256 startingGas = gasleft();
58 | |
59 | * | DataStore _dataStore = dataStore;
60 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(_dataStore, key);
61 | |
62 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelWithdrawalFeatureDisabledKey(address(this)));
63 | |
64 | * | validateRequestCancellation(
65 | * | withdrawal.updatedAtTime(),
66 | | "Withdrawal"
67 | | );
68 | |
69 | * | WithdrawalUtils.cancelWithdrawal(
70 | * | _dataStore,
71 | * | eventEmitter,
72 | * | withdrawalVault,
73 | * | key,
74 | * | withdrawal.account(),
75 | * | startingGas,
76 | * | Keys.USER_INITIATED_CANCEL,
77 | | ""
78 | | );
79 | | }
80 | |
81 | | // @dev executes a withdrawal
82 | | // @param key the key of the withdrawal to execute
83 | | // @param oracleParams OracleUtils.SetPricesParams
84 | * | function executeWithdrawal(
85 | | bytes32 key,
86 | | OracleUtils.SetPricesParams calldata oracleParams
87 | | )
88 | | external
89 | | globalNonReentrant
90 | | onlyOrderKeeper
91 | * | withOraclePrices(oracleParams)
92 | * | {
93 | * | uint256 startingGas = gasleft();
94 | |
95 | * | oracle.validateSequencerUp();
96 | |
97 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
98 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);
99 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);
100 | |
101 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);
102 | |
103 | * | try this._executeWithdrawal{ gas: executionGas }(
104 | * | key,
105 | * | withdrawal,
106 | * | msg.sender,
107 | * | ISwapPricingUtils.SwapPricingType.TwoStep
108 | | ) {
109 | | } catch (bytes memory reasonBytes) {
110 | * | _handleWithdrawalError(
111 | * | key,
112 | * | startingGas,
113 | * | reasonBytes
114 | | );
115 | | }
116 | | }
117 | |
118 | | // @notice this function can only be called for markets where Chainlink
119 | | // on-chain feeds are configured for all the tokens of the market
120 | | // for example, if the market has index token as DOGE, long token as WETH
121 | | // and short token as USDC, Chainlink on-chain feeds must be configured
122 | | // for DOGE, WETH, USDC for this method to be callable for the market
123 | * | function executeAtomicWithdrawal(
124 | | address account,
125 | | WithdrawalUtils.CreateWithdrawalParams calldata params,
126 | | OracleUtils.SetPricesParams calldata oracleParams
127 | | )
128 | | external
129 | | globalNonReentrant
130 | | onlyController
131 | * | withOraclePricesForAtomicAction(oracleParams)
132 | | {
133 | * | FeatureUtils.validateFeature(dataStore, Keys.executeAtomicWithdrawalFeatureDisabledKey(address(this)));
134 | |
135 | * | oracle.validateSequencerUp();
136 | |
137 | * | if (
138 | * | params.longTokenSwapPath.length != 0 ||
139 | | params.shortTokenSwapPath.length != 0
140 | | ) {
141 | * | revert Errors.SwapsNotAllowedForAtomicWithdrawal(
142 | * | params.longTokenSwapPath.length,
143 | * | params.shortTokenSwapPath.length
144 | | );
145 | | }
146 | |
147 | | bytes32 key = WithdrawalUtils.createWithdrawal(
148 | | dataStore,
149 | | eventEmitter,
150 | | withdrawalVault,
151 | | account,
152 | | params
153 | | );
154 | |
155 | | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
156 | |
157 | | this._executeWithdrawal(
158 | | key,
159 | | withdrawal,
160 | | account,
161 | | ISwapPricingUtils.SwapPricingType.Atomic
162 | | );
163 | | }
164 | |
165 | | // @dev simulate execution of a withdrawal to check for any errors
166 | | // @param key the withdrawal key
167 | | // @param params OracleUtils.SimulatePricesParams
168 | | function simulateExecuteWithdrawal(
169 | | bytes32 key,
170 | | OracleUtils.SimulatePricesParams memory params,
171 | | ISwapPricingUtils.SwapPricingType swapPricingType
172 | | ) external
173 | | override
174 | | onlyController
175 | | withSimulatedOraclePrices(params)
176 | | globalNonReentrant
177 | | {
178 | | oracle.validateSequencerUp();
179 | |
180 | | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
181 | |
182 | | this._executeWithdrawal(
183 | | key,
184 | | withdrawal,
185 | | msg.sender,
186 | | swapPricingType
187 | | );
188 | | }
189 | |
190 | | // @dev executes a withdrawal
191 | | // @param oracleParams OracleUtils.SetPricesParams
192 | | // @param keeper the keeper executing the withdrawal
193 | | // @param startingGas the starting gas
194 | * | function _executeWithdrawal(
195 | | bytes32 key,
196 | | Withdrawal.Props memory withdrawal,
197 | | address keeper,
198 | | ISwapPricingUtils.SwapPricingType swapPricingType
199 | * | ) external onlySelf {
200 | * | uint256 startingGas = gasleft();
201 | |
202 | * | FeatureUtils.validateFeature(dataStore, Keys.executeWithdrawalFeatureDisabledKey(address(this)));
203 | |
204 | * | ExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params = ExecuteWithdrawalUtils.ExecuteWithdrawalParams(
205 | * | dataStore,
206 | * | eventEmitter,
207 | * | withdrawalVault,
208 | * | oracle,
209 | * | key,
210 | * | keeper,
211 | * | startingGas,
212 | * | swapPricingType
213 | | );
214 | |
215 | * | ExecuteWithdrawalUtils.executeWithdrawal(params, withdrawal);
216 | | }
217 | |
218 | * | function _handleWithdrawalError(
219 | | bytes32 key,
220 | | uint256 startingGas,
221 | | bytes memory reasonBytes
222 | | ) internal {
223 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);
224 | |
225 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);
226 | |
227 | * | if (
228 | * | OracleUtils.isOracleError(errorSelector) ||
229 | * | errorSelector == Errors.DisabledFeature.selector ||
230 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector
231 | | ) {
232 | |
233 | * | ErrorUtils.revertWithCustomError(reasonBytes);
234 | | }
235 | |
236 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
237 | |
238 | * | WithdrawalUtils.cancelWithdrawal(
239 | * | dataStore,
240 | * | eventEmitter,
241 | * | withdrawalVault,
242 | * | key,
243 | * | msg.sender,
244 | * | startingGas,
245 | * | reason,
246 | * | reasonBytes
247 | | );
248 | | }
249 | | }
250 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/external/ExternalHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/Address.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
9 | |
10 | | import "./IExternalHandler.sol";
11 | | import "../error/Errors.sol";
12 | |
13 | | // contracts with a CONTROLLER role or other roles may need to call external
14 | | // contracts, since these roles may be able to directly change DataStore values
15 | | // or perform other sensitive operations, these contracts should make these calls
16 | | // through ExternalHandler instead
17 | | //
18 | | // note that anyone can make this contract call any function, this should be noted
19 | | // to avoid assumptions of the contract's state in any protocol
20 | | //
21 | | // e.g. some tokens require the approved amount to be zero before the approved amount
22 | | // can be changed, this should be taken into account if calling approve is required for
23 | | // these tokens
24 | * | contract ExternalHandler is IExternalHandler, ReentrancyGuard {
25 | | using Address for address;
26 | | using SafeERC20 for IERC20;
27 | |
28 | | // @notice refundTokens should be unique, this is because the refund loop
29 | | // sends the full refund token balance on each iteration, so if there are
30 | | // duplicate refund token addresses, then only the first refundReceiver
31 | | // for that token would receive the tokens
32 | | function makeExternalCalls(
33 | | address[] memory targets,
34 | | bytes[] memory dataList,
35 | | address[] memory refundTokens,
36 | | address[] memory refundReceivers
37 | | ) external nonReentrant {
38 | | if (targets.length != dataList.length) {
39 | | revert Errors.InvalidExternalCallInput(targets.length, dataList.length);
40 | | }
41 | |
42 | | if (refundTokens.length != refundReceivers.length) {
43 | | revert Errors.InvalidExternalReceiversInput(refundTokens.length, refundReceivers.length);
44 | | }
45 | |
46 | | for (uint256 i; i < targets.length; i++) {
47 | | _makeExternalCall(
48 | | targets[i],
49 | | dataList[i]
50 | | );
51 | | }
52 | |
53 | | for (uint256 i; i < refundTokens.length; i++) {
54 | | IERC20 refundToken = IERC20(refundTokens[i]);
55 | | uint256 balance = refundToken.balanceOf(address(this));
56 | | if (balance > 0) {
57 | | refundToken.safeTransfer(refundReceivers[i], balance);
58 | | }
59 | | }
60 | | }
61 | |
62 | | function _makeExternalCall(
63 | | address target,
64 | | bytes memory data
65 | | ) internal {
66 | | if (!target.isContract()) {
67 | | revert Errors.InvalidExternalCallTarget(target);
68 | | }
69 | |
70 | | (bool success, bytes memory returndata) = target.call(data);
71 | |
72 | | if (!success) {
73 | | revert Errors.ExternalCallFailed(returndata);
74 | | }
75 | | }
76 | | }
77 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/external/IExternalHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | interface IExternalHandler {
6 | | function makeExternalCalls(
7 | | address[] memory targets,
8 | | bytes[] memory dataList,
9 | | address[] memory refundTokens,
10 | | address[] memory refundReceivers
11 | | ) external;
12 | | }
13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/feature/FeatureUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | |
8 | | // @title FeatureUtils
9 | | // @dev Library to validate if a feature is enabled or disabled
10 | | // disabling a feature should only be used if it is absolutely necessary
11 | | // disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders
12 | | // could be disabled while liquidations may remain enabled
13 | | // this could also occur if the chain is not producing blocks and lead to liquidatable positions
14 | | // when block production resumes
15 | | // the effects of disabling features should be carefully considered
16 | * | library FeatureUtils {
17 | | // @dev get whether a feature is disabled
18 | | // @param dataStore DataStore
19 | | // @param key the feature key
20 | | // @return whether the feature is disabled
21 | * | function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {
22 | * | return dataStore.getBool(key);
23 | | }
24 | |
25 | | // @dev validate whether a feature is enabled, reverts if the feature is disabled
26 | | // @param dataStore DataStore
27 | | // @param key the feature key
28 | * | function validateFeature(DataStore dataStore, bytes32 key) internal view {
29 | * | if (isFeatureDisabled(dataStore, key)) {
30 | | revert Errors.DisabledFeature(key);
31 | | }
32 | | }
33 | | }
34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeBatch.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title FeeBatch
6 | | // @dev Struct for fee batches
7 | * | library FeeBatch {
8 | | struct Props {
9 | | address[] feeTokens;
10 | | uint256[] feeAmounts;
11 | | uint256[] remainingAmounts;
12 | | uint256 createdAt;
13 | | }
14 | | }
15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeBatchStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./FeeBatch.sol";
9 | |
10 | | /**
11 | | * @title FeeBatchStoreUtils
12 | | * @dev Library for fee batch storage functions
13 | | */
14 | * | library FeeBatchStoreUtils {
15 | | using FeeBatch for FeeBatch.Props;
16 | |
17 | | bytes32 internal constant FEE_TOKENS = keccak256(abi.encode("FEE_TOKENS"));
18 | | bytes32 internal constant FEE_AMOUNTS = keccak256(abi.encode("FEE_AMOUNTS"));
19 | | bytes32 internal constant REMAINING_AMOUNTS = keccak256(abi.encode("REMAINING_AMOUNTS"));
20 | | bytes32 internal constant CREATED_AT = keccak256(abi.encode("CREATED_AT"));
21 | |
22 | | function get(DataStore dataStore, bytes32 key) internal view returns (FeeBatch.Props memory) {
23 | | FeeBatch.Props memory feeBatch;
24 | | if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) {
25 | | return feeBatch;
26 | | }
27 | |
28 | | feeBatch.feeTokens = dataStore.getAddressArray(
29 | | keccak256(abi.encode(key, FEE_TOKENS))
30 | | );
31 | |
32 | | feeBatch.feeAmounts = dataStore.getUintArray(
33 | | keccak256(abi.encode(key, FEE_AMOUNTS))
34 | | );
35 | |
36 | | feeBatch.remainingAmounts = dataStore.getUintArray(
37 | | keccak256(abi.encode(key, REMAINING_AMOUNTS))
38 | | );
39 | |
40 | | feeBatch.createdAt = dataStore.getUint(
41 | | keccak256(abi.encode(key, CREATED_AT))
42 | | );
43 | |
44 | | return feeBatch;
45 | | }
46 | |
47 | | function set(DataStore dataStore, bytes32 key, FeeBatch.Props memory feeBatch) internal {
48 | | dataStore.addBytes32(
49 | | Keys.FEE_BATCH_LIST,
50 | | key
51 | | );
52 | |
53 | | dataStore.setAddressArray(
54 | | keccak256(abi.encode(key, FEE_TOKENS)),
55 | | feeBatch.feeTokens
56 | | );
57 | |
58 | | dataStore.setUintArray(
59 | | keccak256(abi.encode(key, FEE_AMOUNTS)),
60 | | feeBatch.feeAmounts
61 | | );
62 | |
63 | | dataStore.setUintArray(
64 | | keccak256(abi.encode(key, REMAINING_AMOUNTS)),
65 | | feeBatch.remainingAmounts
66 | | );
67 | |
68 | | dataStore.setUint(
69 | | keccak256(abi.encode(key, CREATED_AT)),
70 | | feeBatch.createdAt
71 | | );
72 | | }
73 | |
74 | | function remove(DataStore dataStore, bytes32 key) internal {
75 | | if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) {
76 | | revert Errors.FeeBatchNotFound(key);
77 | | }
78 | |
79 | | dataStore.removeBytes32(
80 | | Keys.FEE_BATCH_LIST,
81 | | key
82 | | );
83 | |
84 | | dataStore.removeAddressArray(
85 | | keccak256(abi.encode(key, FEE_TOKENS))
86 | | );
87 | |
88 | | dataStore.removeUintArray(
89 | | keccak256(abi.encode(key, FEE_AMOUNTS))
90 | | );
91 | |
92 | | dataStore.removeUintArray(
93 | | keccak256(abi.encode(key, REMAINING_AMOUNTS))
94 | | );
95 | |
96 | | dataStore.removeUint(
97 | | keccak256(abi.encode(key, CREATED_AT))
98 | | );
99 | | }
100 | |
101 | | function getFeeBatchCount(DataStore dataStore) internal view returns (uint256) {
102 | | return dataStore.getAddressCount(Keys.FEE_BATCH_LIST);
103 | | }
104 | |
105 | | function getFeeBatchKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
106 | | return dataStore.getBytes32ValuesAt(Keys.FEE_BATCH_LIST, start, end);
107 | | }
108 | | }
109 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../role/RoleModule.sol";
9 | | import "../fee/FeeUtils.sol";
10 | |
11 | | // @title FeeHandler
12 | * | contract FeeHandler is ReentrancyGuard, RoleModule {
13 | | DataStore public immutable dataStore;
14 | | EventEmitter public immutable eventEmitter;
15 | |
16 | | constructor(
17 | | RoleStore _roleStore,
18 | | DataStore _dataStore,
19 | | EventEmitter _eventEmitter
20 | | ) RoleModule(_roleStore) {
21 | | dataStore = _dataStore;
22 | | eventEmitter = _eventEmitter;
23 | | }
24 | |
25 | | // @dev claim fees from the specified markets
26 | | // @param markets the markets to claim fees from
27 | | // @param tokens the fee tokens to claim
28 | | function claimFees(
29 | | address[] memory markets,
30 | | address[] memory tokens
31 | | ) external nonReentrant onlyFeeKeeper {
32 | | if (markets.length != tokens.length) {
33 | | revert Errors.InvalidClaimFeesInput(markets.length, tokens.length);
34 | | }
35 | |
36 | | address receiver = dataStore.getAddress(Keys.FEE_RECEIVER);
37 | |
38 | | for (uint256 i; i < markets.length; i++) {
39 | | FeeUtils.claimFees(
40 | | dataStore,
41 | | eventEmitter,
42 | | markets[i],
43 | | tokens[i],
44 | | receiver
45 | | );
46 | | }
47 | | }
48 | | }
49 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeSwapUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../v1/IVaultV1.sol";
6 | | import "../v1/IRouterV1.sol";
7 | |
8 | | import "../data/DataStore.sol";
9 | | import "../role/RoleModule.sol";
10 | | import "../fee/FeeUtils.sol";
11 | | import "../fee/FeeBatchStoreUtils.sol";
12 | | import "../market/Market.sol";
13 | | import "../nonce/NonceUtils.sol";
14 | | import "../router/IExchangeRouter.sol";
15 | |
16 | | // @title FeeSwapUtils
17 | * | library FeeSwapUtils {
18 | | function swapFeesUsingV1(
19 | | DataStore dataStore,
20 | | IRouterV1 routerV1,
21 | | address bridgingToken,
22 | | bytes32 feeBatchKey,
23 | | uint256 tokenIndex,
24 | | address[] memory path,
25 | | uint256 swapAmount,
26 | | uint256 minOut
27 | | ) internal {
28 | | (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues(
29 | | dataStore,
30 | | feeBatchKey,
31 | | tokenIndex,
32 | | swapAmount
33 | | );
34 | |
35 | | if (path[path.length - 1] != bridgingToken) {
36 | | revert Errors.InvalidSwapPathForV1(path, bridgingToken);
37 | | }
38 | |
39 | | feeBatch.remainingAmounts[tokenIndex] -= swapAmount;
40 | | FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch);
41 | |
42 | | IERC20(tokenIn).approve(address(routerV1), swapAmount);
43 | | routerV1.swap(path, swapAmount, minOut, address(this));
44 | | }
45 | |
46 | | function swapFeesUsingV2(
47 | | DataStore dataStore,
48 | | address routerV2,
49 | | IExchangeRouter exchangeRouterV2,
50 | | address bridgingToken,
51 | | bytes32 feeBatchKey,
52 | | uint256 tokenIndex,
53 | | address market,
54 | | address[] memory swapPath,
55 | | uint256 swapAmount,
56 | | uint256 executionFee,
57 | | uint256 minOut
58 | | ) internal {
59 | | (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues(
60 | | dataStore,
61 | | feeBatchKey,
62 | | tokenIndex,
63 | | swapAmount
64 | | );
65 | |
66 | | SwapUtils.validateSwapOutputToken(dataStore, swapPath, tokenIn, bridgingToken);
67 | |
68 | | IBaseOrderUtils.CreateOrderParams memory params = _getSwapOrderParamsV2(
69 | | dataStore,
70 | | market,
71 | | tokenIn,
72 | | swapPath,
73 | | swapAmount,
74 | | executionFee,
75 | | minOut
76 | | );
77 | |
78 | | feeBatch.remainingAmounts[tokenIndex] -= swapAmount;
79 | | FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch);
80 | |
81 | | IERC20(tokenIn).approve(routerV2, swapAmount);
82 | | bytes32 orderKey = exchangeRouterV2.createOrder{ value: msg.value }(params);
83 | | dataStore.setBytes32(Keys.feeDistributorSwapFeeBatchKey(orderKey), feeBatchKey);
84 | | dataStore.setUint(Keys.feeDistributorSwapTokenIndexKey(orderKey), tokenIndex);
85 | | }
86 | |
87 | | function _getSwapValues(
88 | | DataStore dataStore,
89 | | bytes32 feeBatchKey,
90 | | uint256 tokenIndex,
91 | | uint256 swapAmount
92 | | ) internal view returns (FeeBatch.Props memory, address) {
93 | | FeeBatch.Props memory feeBatch = FeeBatchStoreUtils.get(dataStore, feeBatchKey);
94 | |
95 | | if (tokenIndex > feeBatch.feeTokens.length) {
96 | | revert Errors.InvalidFeeBatchTokenIndex(tokenIndex, feeBatch.feeTokens.length);
97 | | }
98 | |
99 | | address tokenIn = feeBatch.feeTokens[tokenIndex];
100 | | uint256 remainingAmount = feeBatch.remainingAmounts[tokenIndex];
101 | | if (swapAmount > remainingAmount) {
102 | | revert Errors.InvalidAmountInForFeeBatch(swapAmount, remainingAmount);
103 | | }
104 | |
105 | | return (feeBatch, tokenIn);
106 | | }
107 | |
108 | | function _getSwapOrderParamsV2(
109 | | DataStore dataStore,
110 | | address market,
111 | | address tokenIn,
112 | | address[] memory swapPath,
113 | | uint256 swapAmount,
114 | | uint256 executionFee,
115 | | uint256 minOut
116 | | ) internal view returns (IBaseOrderUtils.CreateOrderParams memory) {
117 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses = IBaseOrderUtils.CreateOrderParamsAddresses(
118 | | address(this), // receiver
119 | | address(this), // cancellationReceiver
120 | | address(this), // callbackContract
121 | | address(0), // uiFeeReceiver
122 | | market, // market
123 | | tokenIn, // initialCollateralToken
124 | | swapPath // swapPath
125 | | );
126 | |
127 | | uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT);
128 | |
129 | | IBaseOrderUtils.CreateOrderParamsNumbers memory numbers = IBaseOrderUtils.CreateOrderParamsNumbers(
130 | | 0, // sizeDeltaUsd
131 | | swapAmount, // initialCollateralDeltaAmount
132 | | 0, // triggerPrice
133 | | 0, // acceptablePrice
134 | | executionFee, // executionFee
135 | | maxCallbackGasLimit, // callbackGasLimit
136 | | minOut // minOutputAmount
137 | | );
138 | |
139 | | IBaseOrderUtils.CreateOrderParams memory params = IBaseOrderUtils.CreateOrderParams(
140 | | addresses, // addresses
141 | | numbers, // numbers
142 | | Order.OrderType.MarketSwap, // orderType
143 | | Order.DecreasePositionSwapType.NoSwap, // decreasePositionSwapType
144 | | false, // isLong
145 | | false, // shouldUnwrapNativeToken
146 | | false, // autoCancel
147 | | bytes32(0) // referralCode
148 | | );
149 | |
150 | | return params;
151 | | }
152 | | }
153 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | |
8 | | import "../event/EventEmitter.sol";
9 | | import "../event/EventUtils.sol";
10 | | import "../utils/Cast.sol";
11 | | import "../utils/AccountUtils.sol";
12 | | import "../market/MarketUtils.sol";
13 | |
14 | | import "../market/MarketToken.sol";
15 | |
16 | | // @title FeeUtils
17 | | // @dev Library for fee actions
18 | * | library FeeUtils {
19 | | using EventUtils for EventUtils.AddressItems;
20 | | using EventUtils for EventUtils.UintItems;
21 | | using EventUtils for EventUtils.IntItems;
22 | | using EventUtils for EventUtils.BoolItems;
23 | | using EventUtils for EventUtils.Bytes32Items;
24 | | using EventUtils for EventUtils.BytesItems;
25 | | using EventUtils for EventUtils.StringItems;
26 | |
27 | | // @dev increment the claimable fee amount
28 | | // @param dataStore DataStore
29 | | // @param eventEmitter EventEmitter
30 | | // @param market the market to increment claimable fees for
31 | | // @param token the fee token
32 | | // @param delta the amount to increment
33 | | // @param feeType the type of the fee
34 | * | function incrementClaimableFeeAmount(
35 | | DataStore dataStore,
36 | | EventEmitter eventEmitter,
37 | | address market,
38 | | address token,
39 | | uint256 delta,
40 | | bytes32 feeType
41 | * | ) internal {
42 | * | if (delta == 0) {
43 | * | return;
44 | | }
45 | |
46 | * | bytes32 key = Keys.claimableFeeAmountKey(market, token);
47 | |
48 | * | uint256 nextValue = dataStore.incrementUint(
49 | * | key,
50 | * | delta
51 | | );
52 | |
53 | * | emitClaimableFeeAmountUpdated(
54 | * | eventEmitter,
55 | * | market,
56 | * | token,
57 | * | delta,
58 | * | nextValue,
59 | * | feeType
60 | | );
61 | | }
62 | |
63 | * | function incrementClaimableUiFeeAmount(
64 | | DataStore dataStore,
65 | | EventEmitter eventEmitter,
66 | | address uiFeeReceiver,
67 | | address market,
68 | | address token,
69 | | uint256 delta,
70 | | bytes32 feeType
71 | | ) internal {
72 | * | if (delta == 0) {
73 | * | return;
74 | | }
75 | |
76 | | uint256 nextValue = dataStore.incrementUint(
77 | | Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver),
78 | | delta
79 | | );
80 | |
81 | | uint256 nextPoolValue = dataStore.incrementUint(
82 | | Keys.claimableUiFeeAmountKey(market, token),
83 | | delta
84 | | );
85 | |
86 | | emitClaimableUiFeeAmountUpdated(
87 | | eventEmitter,
88 | | uiFeeReceiver,
89 | | market,
90 | | token,
91 | | delta,
92 | | nextValue,
93 | | nextPoolValue,
94 | | feeType
95 | | );
96 | | }
97 | |
98 | | // @dev claim fees for the specified market
99 | | // @param dataStore DataStore
100 | | // @param eventEmitter EventEmitter
101 | | // @param market the market to claim fees for
102 | | // @param token the fee token
103 | | // @param receiver the receiver of the claimed fees
104 | | function claimFees(
105 | | DataStore dataStore,
106 | | EventEmitter eventEmitter,
107 | | address market,
108 | | address token,
109 | | address receiver
110 | | ) internal returns (uint256) {
111 | | AccountUtils.validateReceiver(receiver);
112 | |
113 | | bytes32 key = Keys.claimableFeeAmountKey(market, token);
114 | |
115 | | uint256 feeAmount = dataStore.getUint(key);
116 | | dataStore.setUint(key, 0);
117 | |
118 | | MarketToken(payable(market)).transferOut(
119 | | token,
120 | | receiver,
121 | | feeAmount
122 | | );
123 | |
124 | | MarketUtils.validateMarketTokenBalance(dataStore, market);
125 | |
126 | | emitFeesClaimed(
127 | | eventEmitter,
128 | | market,
129 | | receiver,
130 | | feeAmount
131 | | );
132 | |
133 | | return feeAmount;
134 | | }
135 | |
136 | | function claimUiFees(
137 | | DataStore dataStore,
138 | | EventEmitter eventEmitter,
139 | | address uiFeeReceiver,
140 | | address market,
141 | | address token,
142 | | address receiver
143 | | ) internal returns (uint256) {
144 | | AccountUtils.validateReceiver(receiver);
145 | |
146 | | bytes32 key = Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver);
147 | |
148 | | uint256 feeAmount = dataStore.getUint(key);
149 | | dataStore.setUint(key, 0);
150 | |
151 | | uint256 nextPoolValue = dataStore.decrementUint(
152 | | Keys.claimableUiFeeAmountKey(market, token),
153 | | feeAmount
154 | | );
155 | |
156 | | MarketToken(payable(market)).transferOut(
157 | | token,
158 | | receiver,
159 | | feeAmount
160 | | );
161 | |
162 | | MarketUtils.validateMarketTokenBalance(dataStore, market);
163 | |
164 | | emitUiFeesClaimed(
165 | | eventEmitter,
166 | | uiFeeReceiver,
167 | | market,
168 | | receiver,
169 | | feeAmount,
170 | | nextPoolValue
171 | | );
172 | |
173 | | return feeAmount;
174 | | }
175 | |
176 | * | function emitClaimableFeeAmountUpdated(
177 | | EventEmitter eventEmitter,
178 | | address market,
179 | | address token,
180 | | uint256 delta,
181 | | uint256 nextValue,
182 | | bytes32 feeType
183 | * | ) internal {
184 | * | EventUtils.EventLogData memory eventData;
185 | |
186 | * | eventData.addressItems.initItems(2);
187 | * | eventData.addressItems.setItem(0, "market", market);
188 | * | eventData.addressItems.setItem(1, "token", token);
189 | |
190 | * | eventData.uintItems.initItems(2);
191 | * | eventData.uintItems.setItem(0, "delta", delta);
192 | * | eventData.uintItems.setItem(1, "nextValue", nextValue);
193 | |
194 | * | eventData.bytes32Items.initItems(1);
195 | * | eventData.bytes32Items.setItem(0, "feeType", feeType);
196 | |
197 | * | eventEmitter.emitEventLog2(
198 | | "ClaimableFeeAmountUpdated",
199 | * | Cast.toBytes32(market),
200 | * | feeType,
201 | * | eventData
202 | | );
203 | | }
204 | |
205 | | function emitClaimableUiFeeAmountUpdated(
206 | | EventEmitter eventEmitter,
207 | | address uiFeeReceiver,
208 | | address market,
209 | | address token,
210 | | uint256 delta,
211 | | uint256 nextValue,
212 | | uint256 nextPoolValue,
213 | | bytes32 feeType
214 | | ) internal {
215 | | EventUtils.EventLogData memory eventData;
216 | |
217 | | eventData.addressItems.initItems(3);
218 | | eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver);
219 | | eventData.addressItems.setItem(1, "market", market);
220 | | eventData.addressItems.setItem(2, "token", token);
221 | |
222 | | eventData.uintItems.initItems(3);
223 | | eventData.uintItems.setItem(0, "delta", delta);
224 | | eventData.uintItems.setItem(1, "nextValue", nextValue);
225 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
226 | |
227 | | eventData.bytes32Items.initItems(1);
228 | | eventData.bytes32Items.setItem(0, "feeType", feeType);
229 | |
230 | | eventEmitter.emitEventLog2(
231 | | "ClaimableUiFeeAmountUpdated",
232 | | Cast.toBytes32(market),
233 | | feeType,
234 | | eventData
235 | | );
236 | | }
237 | |
238 | | function emitFeesClaimed(
239 | | EventEmitter eventEmitter,
240 | | address market,
241 | | address receiver,
242 | | uint256 feeAmount
243 | | ) internal {
244 | | EventUtils.EventLogData memory eventData;
245 | |
246 | | eventData.addressItems.initItems(2);
247 | | eventData.addressItems.setItem(0, "market", market);
248 | | eventData.addressItems.setItem(1, "receiver", receiver);
249 | |
250 | | eventData.uintItems.initItems(1);
251 | | eventData.uintItems.setItem(0, "feeAmount", feeAmount);
252 | |
253 | | eventEmitter.emitEventLog1(
254 | | "FeesClaimed",
255 | | Cast.toBytes32(market),
256 | | eventData
257 | | );
258 | | }
259 | |
260 | | function emitUiFeesClaimed(
261 | | EventEmitter eventEmitter,
262 | | address uiFeeReceiver,
263 | | address market,
264 | | address receiver,
265 | | uint256 feeAmount,
266 | | uint256 nextPoolValue
267 | | ) internal {
268 | | EventUtils.EventLogData memory eventData;
269 | |
270 | | eventData.addressItems.initItems(3);
271 | | eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver);
272 | | eventData.addressItems.setItem(1, "market", market);
273 | | eventData.addressItems.setItem(2, "receiver", receiver);
274 | |
275 | | eventData.uintItems.initItems(2);
276 | | eventData.uintItems.setItem(0, "feeAmount", feeAmount);
277 | | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
278 | |
279 | | eventEmitter.emitEventLog1(
280 | | "UiFeesClaimed",
281 | | Cast.toBytes32(market),
282 | | eventData
283 | | );
284 | | }
285 | | }
286 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gas/GasUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../callback/CallbackUtils.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../data/Keys.sol";
9 | | import "../utils/Precision.sol";
10 | |
11 | | import "../deposit/Deposit.sol";
12 | | import "../withdrawal/Withdrawal.sol";
13 | | import "../shift/Shift.sol";
14 | | import "../order/Order.sol";
15 | | import "../order/BaseOrderUtils.sol";
16 | |
17 | | import "../bank/StrictBank.sol";
18 | |
19 | | // @title GasUtils
20 | | // @dev Library for execution fee estimation and payments
21 | * | library GasUtils {
22 | | using Deposit for Deposit.Props;
23 | | using Withdrawal for Withdrawal.Props;
24 | | using Shift for Shift.Props;
25 | | using Order for Order.Props;
26 | | using GlvDeposit for GlvDeposit.Props;
27 | |
28 | | using EventUtils for EventUtils.AddressItems;
29 | | using EventUtils for EventUtils.UintItems;
30 | | using EventUtils for EventUtils.IntItems;
31 | | using EventUtils for EventUtils.BoolItems;
32 | | using EventUtils for EventUtils.Bytes32Items;
33 | | using EventUtils for EventUtils.BytesItems;
34 | | using EventUtils for EventUtils.StringItems;
35 | |
36 | | // @param keeper address of the keeper
37 | | // @param amount the amount of execution fee received
38 | | event KeeperExecutionFee(address keeper, uint256 amount);
39 | | // @param user address of the user
40 | | // @param amount the amount of execution fee refunded
41 | | event UserRefundFee(address user, uint256 amount);
42 | |
43 | | function getMinHandleExecutionErrorGas(
44 | | DataStore dataStore
45 | | ) internal view returns (uint256) {
46 | | return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS);
47 | | }
48 | |
49 | * | function getMinHandleExecutionErrorGasToForward(
50 | | DataStore dataStore
51 | * | ) internal view returns (uint256) {
52 | * | return
53 | * | dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD);
54 | | }
55 | |
56 | * | function getMinAdditionalGasForExecution(
57 | | DataStore dataStore
58 | * | ) internal view returns (uint256) {
59 | * | return dataStore.getUint(Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION);
60 | | }
61 | |
62 | * | function getExecutionGas(
63 | | DataStore dataStore,
64 | | uint256 startingGas
65 | * | ) internal view returns (uint256) {
66 | * | uint256 minHandleExecutionErrorGasToForward = GasUtils
67 | * | .getMinHandleExecutionErrorGasToForward(dataStore);
68 | * | if (startingGas < minHandleExecutionErrorGasToForward) {
69 | | revert Errors.InsufficientExecutionGasForErrorHandling(
70 | | startingGas,
71 | | minHandleExecutionErrorGasToForward
72 | | );
73 | | }
74 | |
75 | * | return startingGas - minHandleExecutionErrorGasToForward;
76 | | }
77 | |
78 | * | function validateExecutionGas(
79 | | DataStore dataStore,
80 | | uint256 startingGas,
81 | | uint256 estimatedGasLimit
82 | * | ) internal view {
83 | * | uint256 minAdditionalGasForExecution = getMinAdditionalGasForExecution(
84 | * | dataStore
85 | | );
86 | * | if (startingGas < estimatedGasLimit + minAdditionalGasForExecution) {
87 | | revert Errors.InsufficientExecutionGas(
88 | | startingGas,
89 | | estimatedGasLimit,
90 | | minAdditionalGasForExecution
91 | | );
92 | | }
93 | | }
94 | |
95 | | // a minimum amount of gas is required to be left for cancellation
96 | | // to prevent potential blocking of cancellations by malicious contracts using e.g. large revert reasons
97 | | //
98 | | // during the estimateGas call by keepers, an insufficient amount of gas may be estimated
99 | | // the amount estimated may be insufficient for execution but sufficient for cancellaton
100 | | // this could lead to invalid cancellations due to insufficient gas used by keepers
101 | | //
102 | | // to help prevent this, out of gas errors are attempted to be caught and reverted for estimateGas calls
103 | | //
104 | | // a malicious user could cause the estimateGas call of a keeper to fail, in which case the keeper could
105 | | // still attempt to execute the transaction with a reasonable gas limit
106 | * | function validateExecutionErrorGas(
107 | | DataStore dataStore,
108 | | bytes memory reasonBytes
109 | | ) internal view {
110 | | // skip the validation if the execution did not fail due to an out of gas error
111 | | // also skip the validation if this is not invoked in an estimateGas call (tx.origin != address(0))
112 | * | if (reasonBytes.length != 0 || tx.origin != address(0)) {
113 | * | return;
114 | | }
115 | |
116 | | uint256 gas = gasleft();
117 | | uint256 minHandleExecutionErrorGas = getMinHandleExecutionErrorGas(
118 | | dataStore
119 | | );
120 | |
121 | | if (gas < minHandleExecutionErrorGas) {
122 | | revert Errors.InsufficientHandleExecutionErrorGas(
123 | | gas,
124 | | minHandleExecutionErrorGas
125 | | );
126 | | }
127 | | }
128 | |
129 | | struct PayExecutionFeeCache {
130 | | uint256 refundFeeAmount;
131 | | bool refundWasSent;
132 | | }
133 | |
134 | | // @dev pay the keeper the execution fee and refund any excess amount
135 | | //
136 | | // @param dataStore DataStore
137 | | // @param bank the StrictBank contract holding the execution fee
138 | | // @param executionFee the executionFee amount
139 | | // @param startingGas the starting gas
140 | | // @param oraclePriceCount number of oracle prices
141 | | // @param keeper the keeper to pay
142 | | // @param refundReceiver the account that should receive any excess gas refunds
143 | * | function payExecutionFee(
144 | | DataStore dataStore,
145 | | EventEmitter eventEmitter,
146 | | StrictBank bank,
147 | | bytes32 key,
148 | | address callbackContract,
149 | | uint256 executionFee,
150 | | uint256 startingGas,
151 | | uint256 oraclePriceCount,
152 | | address keeper,
153 | | address refundReceiver
154 | * | ) internal {
155 | * | if (executionFee == 0) {
156 | * | return;
157 | | }
158 | |
159 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
160 | | // startingGas -= gasleft() / 63; //NOTE: foundry bug hotfix: comment out
161 | * | uint256 gasUsed = startingGas - gasleft();
162 | |
163 | | // each internal call forwards 63/64 of the remaining gas
164 | * | uint256 executionFeeForKeeper = adjustGasUsage(
165 | * | dataStore,
166 | * | gasUsed,
167 | * | oraclePriceCount
168 | * | ) * tx.gasprice;
169 | |
170 | * | if (executionFeeForKeeper > executionFee) {
171 | * | executionFeeForKeeper = executionFee;
172 | | }
173 | |
174 | * | bank.transferOutNativeToken(keeper, executionFeeForKeeper);
175 | |
176 | * | emitKeeperExecutionFee(eventEmitter, keeper, executionFeeForKeeper);
177 | |
178 | * | PayExecutionFeeCache memory cache;
179 | |
180 | * | cache.refundFeeAmount = executionFee - executionFeeForKeeper;
181 | * | if (cache.refundFeeAmount == 0) {
182 | * | return;
183 | | }
184 | |
185 | * | address _wnt = dataStore.getAddress(Keys.WNT);
186 | * | bank.transferOut(_wnt, address(this), cache.refundFeeAmount);
187 | |
188 | * | IWNT(_wnt).withdraw(cache.refundFeeAmount);
189 | |
190 | * | EventUtils.EventLogData memory eventData;
191 | |
192 | * | cache.refundWasSent = CallbackUtils.refundExecutionFee(
193 | * | dataStore,
194 | * | key,
195 | * | callbackContract,
196 | * | cache.refundFeeAmount,
197 | * | eventData
198 | | );
199 | |
200 | * | if (cache.refundWasSent) {
201 | * | emitExecutionFeeRefundCallback(
202 | * | eventEmitter,
203 | * | callbackContract,
204 | * | cache.refundFeeAmount
205 | | );
206 | | } else {
207 | | TokenUtils.sendNativeToken(
208 | | dataStore,
209 | | refundReceiver,
210 | | cache.refundFeeAmount
211 | | );
212 | | emitExecutionFeeRefund(
213 | | eventEmitter,
214 | | refundReceiver,
215 | | cache.refundFeeAmount
216 | | );
217 | | }
218 | | }
219 | |
220 | | // @dev validate that the provided executionFee is sufficient based on the estimatedGasLimit
221 | | // @param dataStore DataStore
222 | | // @param estimatedGasLimit the estimated gas limit
223 | | // @param executionFee the execution fee provided
224 | | // @param oraclePriceCount
225 | * | function validateExecutionFee(
226 | | DataStore dataStore,
227 | | uint256 estimatedGasLimit,
228 | | uint256 executionFee,
229 | | uint256 oraclePriceCount
230 | * | ) internal view {
231 | * | uint256 gasLimit = adjustGasLimitForEstimate(
232 | * | dataStore,
233 | * | estimatedGasLimit,
234 | * | oraclePriceCount
235 | | );
236 | * | uint256 minExecutionFee = gasLimit * tx.gasprice;
237 | * | if (executionFee < minExecutionFee) {
238 | * | revert Errors.InsufficientExecutionFee(
239 | * | minExecutionFee,
240 | * | executionFee
241 | | );
242 | | }
243 | | }
244 | |
245 | | // @dev adjust the gas usage to pay a small amount to keepers
246 | | // @param dataStore DataStore
247 | | // @param gasUsed the amount of gas used
248 | | // @param oraclePriceCount number of oracle prices
249 | * | function adjustGasUsage(
250 | | DataStore dataStore,
251 | | uint256 gasUsed,
252 | | uint256 oraclePriceCount
253 | * | ) internal view returns (uint256) {
254 | | // gas measurements are done after the call to withOraclePrices
255 | | // withOraclePrices may consume a significant amount of gas
256 | | // the baseGasLimit used to calculate the execution cost
257 | | // should be adjusted to account for this
258 | | // additionally, a transaction could fail midway through an execution transaction
259 | | // before being cancelled, the possibility of this additional gas cost should
260 | | // be considered when setting the baseGasLimit
261 | * | uint256 baseGasLimit = dataStore.getUint(
262 | | Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1
263 | | );
264 | * | baseGasLimit +=
265 | * | dataStore.getUint(Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE) *
266 | * | oraclePriceCount;
267 | | // the gas cost is estimated based on the gasprice of the request txn
268 | | // the actual cost may be higher if the gasprice is higher in the execution txn
269 | | // the multiplierFactor should be adjusted to account for this
270 | * | uint256 multiplierFactor = dataStore.getUint(
271 | | Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR
272 | | );
273 | * | uint256 gasLimit = baseGasLimit +
274 | * | Precision.applyFactor(gasUsed, multiplierFactor);
275 | * | return gasLimit;
276 | | }
277 | |
278 | | // @dev adjust the estimated gas limit to help ensure the execution fee is sufficient during
279 | | // the actual execution
280 | | // @param dataStore DataStore
281 | | // @param estimatedGasLimit the estimated gas limit
282 | * | function adjustGasLimitForEstimate(
283 | | DataStore dataStore,
284 | | uint256 estimatedGasLimit,
285 | | uint256 oraclePriceCount
286 | * | ) internal view returns (uint256) {
287 | * | uint256 baseGasLimit = dataStore.getUint(
288 | | Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1
289 | | );
290 | * | baseGasLimit +=
291 | * | dataStore.getUint(Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) *
292 | * | oraclePriceCount;
293 | * | uint256 multiplierFactor = dataStore.getUint(
294 | | Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR
295 | | );
296 | * | uint256 gasLimit = baseGasLimit +
297 | * | Precision.applyFactor(estimatedGasLimit, multiplierFactor);
298 | * | return gasLimit;
299 | | }
300 | |
301 | | // @dev get estimated number of oracle prices for deposit
302 | | // @param swapsCount number of swaps in the deposit
303 | * | function estimateDepositOraclePriceCount(
304 | | uint256 swapsCount
305 | * | ) internal pure returns (uint256) {
306 | * | return 3 + swapsCount;
307 | | }
308 | |
309 | | // @dev get estimated number of oracle prices for withdrawal
310 | | // @param swapsCount number of swaps in the withdrawal
311 | * | function estimateWithdrawalOraclePriceCount(
312 | | uint256 swapsCount
313 | * | ) internal pure returns (uint256) {
314 | * | return 3 + swapsCount;
315 | | }
316 | |
317 | | // @dev get estimated number of oracle prices for order
318 | | // @param swapsCount number of swaps in the order
319 | * | function estimateOrderOraclePriceCount(
320 | | uint256 swapsCount
321 | * | ) internal pure returns (uint256) {
322 | * | return 3 + swapsCount;
323 | | }
324 | |
325 | | // @dev get estimated number of oracle prices for shift
326 | | function estimateShiftOraclePriceCount() internal pure returns (uint256) {
327 | | return 4;
328 | | }
329 | |
330 | | // @dev get estimated number of oracle prices for glv deposit
331 | | // @param marketCount number of markets in the glv
332 | | // @param swapsCount number of swaps in the glv deposit
333 | | function estimateGlvDepositOraclePriceCount(
334 | | uint256 marketCount,
335 | | uint256 swapsCount
336 | | ) internal pure returns (uint256) {
337 | | return 2 + marketCount + swapsCount;
338 | | }
339 | |
340 | | // @dev the estimated gas limit for deposits
341 | | // @param dataStore DataStore
342 | | // @param deposit the deposit to estimate the gas limit for
343 | * | function estimateExecuteDepositGasLimit(
344 | | DataStore dataStore,
345 | | Deposit.Props memory deposit
346 | * | ) internal view returns (uint256) {
347 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
348 | * | uint256 swapCount = deposit.longTokenSwapPath().length +
349 | * | deposit.shortTokenSwapPath().length;
350 | * | uint256 gasForSwaps = swapCount * gasPerSwap;
351 | |
352 | * | if (
353 | * | deposit.initialLongTokenAmount() == 0 ||
354 | * | deposit.initialShortTokenAmount() == 0
355 | | ) {
356 | | return
357 | | dataStore.getUint(Keys.depositGasLimitKey(true)) +
358 | | deposit.callbackGasLimit() +
359 | | gasForSwaps;
360 | | }
361 | |
362 | * | return
363 | * | dataStore.getUint(Keys.depositGasLimitKey(false)) +
364 | * | deposit.callbackGasLimit() +
365 | * | gasForSwaps;
366 | | }
367 | |
368 | | // @dev the estimated gas limit for withdrawals
369 | | // @param dataStore DataStore
370 | | // @param withdrawal the withdrawal to estimate the gas limit for
371 | * | function estimateExecuteWithdrawalGasLimit(
372 | | DataStore dataStore,
373 | | Withdrawal.Props memory withdrawal
374 | * | ) internal view returns (uint256) {
375 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
376 | * | uint256 swapCount = withdrawal.longTokenSwapPath().length +
377 | * | withdrawal.shortTokenSwapPath().length;
378 | * | uint256 gasForSwaps = swapCount * gasPerSwap;
379 | |
380 | * | return
381 | * | dataStore.getUint(Keys.withdrawalGasLimitKey()) +
382 | * | withdrawal.callbackGasLimit() +
383 | * | gasForSwaps;
384 | | }
385 | |
386 | | // @dev the estimated gas limit for shifts
387 | | // @param dataStore DataStore
388 | | // @param shift the shift to estimate the gas limit for
389 | | function estimateExecuteShiftGasLimit(
390 | | DataStore dataStore,
391 | | Shift.Props memory shift
392 | | ) internal view returns (uint256) {
393 | | return
394 | | dataStore.getUint(Keys.shiftGasLimitKey()) +
395 | | shift.callbackGasLimit();
396 | | }
397 | |
398 | | // @dev the estimated gas limit for orders
399 | | // @param dataStore DataStore
400 | | // @param order the order to estimate the gas limit for
401 | * | function estimateExecuteOrderGasLimit(
402 | | DataStore dataStore,
403 | | Order.Props memory order
404 | * | ) internal view returns (uint256) {
405 | * | if (BaseOrderUtils.isIncreaseOrder(order.orderType())) {
406 | * | return estimateExecuteIncreaseOrderGasLimit(dataStore, order);
407 | | }
408 | |
409 | * | if (BaseOrderUtils.isDecreaseOrder(order.orderType())) {
410 | * | return estimateExecuteDecreaseOrderGasLimit(dataStore, order);
411 | | }
412 | |
413 | * | if (BaseOrderUtils.isSwapOrder(order.orderType())) {
414 | * | return estimateExecuteSwapOrderGasLimit(dataStore, order);
415 | | }
416 | |
417 | | revert Errors.UnsupportedOrderType(uint256(order.orderType()));
418 | | }
419 | |
420 | | // @dev the estimated gas limit for increase orders
421 | | // @param dataStore DataStore
422 | | // @param order the order to estimate the gas limit for
423 | * | function estimateExecuteIncreaseOrderGasLimit(
424 | | DataStore dataStore,
425 | | Order.Props memory order
426 | * | ) internal view returns (uint256) {
427 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
428 | * | return
429 | * | dataStore.getUint(Keys.increaseOrderGasLimitKey()) +
430 | * | gasPerSwap *
431 | * | order.swapPath().length +
432 | * | order.callbackGasLimit();
433 | | }
434 | |
435 | | // @dev the estimated gas limit for decrease orders
436 | | // @param dataStore DataStore
437 | | // @param order the order to estimate the gas limit for
438 | * | function estimateExecuteDecreaseOrderGasLimit(
439 | | DataStore dataStore,
440 | | Order.Props memory order
441 | * | ) internal view returns (uint256) {
442 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
443 | * | uint256 swapCount = order.swapPath().length;
444 | * | if (
445 | * | order.decreasePositionSwapType() !=
446 | * | Order.DecreasePositionSwapType.NoSwap
447 | | ) {
448 | * | swapCount += 1;
449 | | }
450 | |
451 | * | return
452 | * | dataStore.getUint(Keys.decreaseOrderGasLimitKey()) +
453 | * | gasPerSwap *
454 | * | swapCount +
455 | * | order.callbackGasLimit();
456 | | }
457 | |
458 | | // @dev the estimated gas limit for swap orders
459 | | // @param dataStore DataStore
460 | | // @param order the order to estimate the gas limit for
461 | * | function estimateExecuteSwapOrderGasLimit(
462 | | DataStore dataStore,
463 | | Order.Props memory order
464 | * | ) internal view returns (uint256) {
465 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
466 | * | return
467 | * | dataStore.getUint(Keys.swapOrderGasLimitKey()) +
468 | * | gasPerSwap *
469 | * | order.swapPath().length +
470 | * | order.callbackGasLimit();
471 | | }
472 | |
473 | | // @dev the estimated gas limit for glv deposits
474 | | // @param dataStore DataStore
475 | | // @param deposit the deposit to estimate the gas limit for
476 | | function estimateExecuteGlvDepositGasLimit(
477 | | DataStore dataStore,
478 | | GlvDeposit.Props memory glvDeposit,
479 | | uint256 marketCount
480 | | ) internal view returns (uint256) {
481 | | // glv deposit execution gas consumption depends on the amount of markets
482 | | uint256 gasPerGlvPerMarket = dataStore.getUint(
483 | | Keys.glvPerMarketGasLimitKey()
484 | | );
485 | | uint256 gasForGlvMarkets = gasPerGlvPerMarket * marketCount;
486 | | uint256 glvDepositGasLimit = dataStore.getUint(
487 | | Keys.glvDepositGasLimitKey()
488 | | );
489 | |
490 | | uint256 gasLimit = glvDepositGasLimit +
491 | | glvDeposit.callbackGasLimit() +
492 | | gasForGlvMarkets;
493 | |
494 | | if (glvDeposit.market() == glvDeposit.initialLongToken()) {
495 | | // user provided GM, no separate deposit will be created and executed in this case
496 | | return gasLimit;
497 | | }
498 | |
499 | | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
500 | | uint256 swapCount = glvDeposit.longTokenSwapPath().length +
501 | | glvDeposit.shortTokenSwapPath().length;
502 | | uint256 gasForSwaps = swapCount * gasPerSwap;
503 | |
504 | | if (
505 | | glvDeposit.initialLongTokenAmount() == 0 ||
506 | | glvDeposit.initialShortTokenAmount() == 0
507 | | ) {
508 | | return
509 | | gasLimit +
510 | | dataStore.getUint(Keys.depositGasLimitKey(true)) +
511 | | gasForSwaps;
512 | | }
513 | | return
514 | | gasLimit +
515 | | dataStore.getUint(Keys.depositGasLimitKey(false)) +
516 | | gasForSwaps;
517 | | }
518 | |
519 | * | function emitKeeperExecutionFee(
520 | | EventEmitter eventEmitter,
521 | | address keeper,
522 | | uint256 executionFeeAmount
523 | * | ) internal {
524 | * | EventUtils.EventLogData memory eventData;
525 | |
526 | * | eventData.addressItems.initItems(1);
527 | * | eventData.addressItems.setItem(0, "keeper", keeper);
528 | |
529 | * | eventData.uintItems.initItems(1);
530 | * | eventData.uintItems.setItem(
531 | * | 0,
532 | | "executionFeeAmount",
533 | * | executionFeeAmount
534 | | );
535 | |
536 | * | eventEmitter.emitEventLog1(
537 | | "KeeperExecutionFee",
538 | * | Cast.toBytes32(keeper),
539 | * | eventData
540 | | );
541 | | }
542 | |
543 | | function emitExecutionFeeRefund(
544 | | EventEmitter eventEmitter,
545 | | address receiver,
546 | | uint256 refundFeeAmount
547 | | ) internal {
548 | | EventUtils.EventLogData memory eventData;
549 | |
550 | | eventData.addressItems.initItems(1);
551 | | eventData.addressItems.setItem(0, "receiver", receiver);
552 | |
553 | | eventData.uintItems.initItems(1);
554 | | eventData.uintItems.setItem(0, "refundFeeAmount", refundFeeAmount);
555 | |
556 | | eventEmitter.emitEventLog1(
557 | | "ExecutionFeeRefund",
558 | | Cast.toBytes32(receiver),
559 | | eventData
560 | | );
561 | | }
562 | |
563 | * | function emitExecutionFeeRefundCallback(
564 | | EventEmitter eventEmitter,
565 | | address callbackContract,
566 | | uint256 refundFeeAmount
567 | * | ) internal {
568 | * | EventUtils.EventLogData memory eventData;
569 | |
570 | * | eventData.addressItems.initItems(1);
571 | * | eventData.addressItems.setItem(0, "callbackContract", callbackContract);
572 | |
573 | * | eventData.uintItems.initItems(1);
574 | * | eventData.uintItems.setItem(0, "refundFeeAmount", refundFeeAmount);
575 | |
576 | * | eventEmitter.emitEventLog1(
577 | | "ExecutionFeeRefundCallback",
578 | * | Cast.toBytes32(callbackContract),
579 | * | eventData
580 | | );
581 | | }
582 | | }
583 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/Glv.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6 | | import "../bank/StrictBank.sol";
7 | |
8 | | contract Glv is ERC20, StrictBank {
9 | | constructor(
10 | | RoleStore _roleStore,
11 | | DataStore _dataStore
12 | | ) ERC20("GMX Liquidity Vault", "GLV") StrictBank(_roleStore, _dataStore) {
13 | | }
14 | |
15 | | function mint(address account, uint256 amount) external onlyController {
16 | | _mint(account, amount);
17 | | }
18 | |
19 | | function burn(address account, uint256 amount) external onlyController {
20 | | _burn(account, amount);
21 | | }
22 | | }
23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDeposit.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title GlvDeposit
6 | | // @dev Struct for GLV deposits
7 | * | library GlvDeposit {
8 | | // @dev there is a limit on the number of fields a struct can have when being passed
9 | | // or returned as a memory variable which can cause "Stack too deep" errors
10 | | // use sub-structs to avoid this issue
11 | | // @param addresses address values
12 | | // @param numbers number values
13 | | // @param flags boolean values
14 | | struct Props {
15 | | Addresses addresses;
16 | | Numbers numbers;
17 | | Flags flags;
18 | | }
19 | |
20 | | // @param account the account depositing liquidity
21 | | // @param receiver the address to send the liquidity tokens to
22 | | // @param callbackContract the callback contract
23 | | // @param uiFeeReceiver the ui fee receiver
24 | | // @param market the market to deposit to
25 | | struct Addresses {
26 | | address glv;
27 | | address account;
28 | | address receiver;
29 | | address callbackContract;
30 | | address uiFeeReceiver;
31 | | address market;
32 | | address initialLongToken;
33 | | address initialShortToken;
34 | | address[] longTokenSwapPath;
35 | | address[] shortTokenSwapPath;
36 | | }
37 | |
38 | | // @param initialLongTokenAmount the amount of long tokens to deposit
39 | | // @param initialShortTokenAmount the amount of short tokens to deposit
40 | | // @param minGlvTokens the minimum acceptable number of Glv tokens
41 | | // @param updatedAtBlock the block that the deposit was last updated at
42 | | // sending funds back to the user in case the deposit gets cancelled
43 | | // @param executionFee the execution fee for keepers
44 | | // @param callbackGasLimit the gas limit for the callbackContract
45 | | struct Numbers {
46 | | uint256 initialLongTokenAmount;
47 | | uint256 initialShortTokenAmount;
48 | | uint256 minGlvTokens;
49 | | uint256 updatedAtBlock;
50 | | uint256 updatedAtTime;
51 | | uint256 executionFee;
52 | | uint256 callbackGasLimit;
53 | | }
54 | |
55 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when
56 | | struct Flags {
57 | | bool shouldUnwrapNativeToken;
58 | | }
59 | |
60 | |
61 | | function account(Props memory props) internal pure returns (address) {
62 | | return props.addresses.account;
63 | | }
64 | |
65 | | function setAccount(Props memory props, address value) internal pure {
66 | | props.addresses.account = value;
67 | | }
68 | |
69 | | function receiver(Props memory props) internal pure returns (address) {
70 | | return props.addresses.receiver;
71 | | }
72 | |
73 | | function setReceiver(Props memory props, address value) internal pure {
74 | | props.addresses.receiver = value;
75 | | }
76 | |
77 | | function callbackContract(Props memory props) internal pure returns (address) {
78 | | return props.addresses.callbackContract;
79 | | }
80 | |
81 | | function setCallbackContract(Props memory props, address value) internal pure {
82 | | props.addresses.callbackContract = value;
83 | | }
84 | |
85 | | function uiFeeReceiver(Props memory props) internal pure returns (address) {
86 | | return props.addresses.uiFeeReceiver;
87 | | }
88 | |
89 | | function setUiFeeReceiver(Props memory props, address value) internal pure {
90 | | props.addresses.uiFeeReceiver = value;
91 | | }
92 | |
93 | | function glv(Props memory props) internal pure returns (address) {
94 | | return props.addresses.glv;
95 | | }
96 | |
97 | | function setGlv(Props memory props, address value) internal pure {
98 | | props.addresses.glv = value;
99 | | }
100 | |
101 | | function market(Props memory props) internal pure returns (address) {
102 | | return props.addresses.market;
103 | | }
104 | |
105 | | function setMarket(Props memory props, address value) internal pure {
106 | | props.addresses.market = value;
107 | | }
108 | |
109 | | function initialLongToken(Props memory props) internal pure returns (address) {
110 | | return props.addresses.initialLongToken;
111 | | }
112 | |
113 | | function setInitialLongToken(Props memory props, address value) internal pure {
114 | | props.addresses.initialLongToken = value;
115 | | }
116 | |
117 | | function initialShortToken(Props memory props) internal pure returns (address) {
118 | | return props.addresses.initialShortToken;
119 | | }
120 | |
121 | | function setInitialShortToken(Props memory props, address value) internal pure {
122 | | props.addresses.initialShortToken = value;
123 | | }
124 | |
125 | | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
126 | | return props.addresses.longTokenSwapPath;
127 | | }
128 | |
129 | | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {
130 | | props.addresses.longTokenSwapPath = value;
131 | | }
132 | |
133 | | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
134 | | return props.addresses.shortTokenSwapPath;
135 | | }
136 | |
137 | | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {
138 | | props.addresses.shortTokenSwapPath = value;
139 | | }
140 | |
141 | | function initialLongTokenAmount(Props memory props) internal pure returns (uint256) {
142 | | return props.numbers.initialLongTokenAmount;
143 | | }
144 | |
145 | | function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure {
146 | | props.numbers.initialLongTokenAmount = value;
147 | | }
148 | |
149 | | function initialShortTokenAmount(Props memory props) internal pure returns (uint256) {
150 | | return props.numbers.initialShortTokenAmount;
151 | | }
152 | |
153 | | function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure {
154 | | props.numbers.initialShortTokenAmount = value;
155 | | }
156 | |
157 | | function minGlvTokens(Props memory props) internal pure returns (uint256) {
158 | | return props.numbers.minGlvTokens;
159 | | }
160 | |
161 | | function setMinGlvTokens(Props memory props, uint256 value) internal pure {
162 | | props.numbers.minGlvTokens = value;
163 | | }
164 | |
165 | | function updatedAtBlock(Props memory props) internal pure returns (uint256) {
166 | | return props.numbers.updatedAtBlock;
167 | | }
168 | |
169 | | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
170 | | props.numbers.updatedAtBlock = value;
171 | | }
172 | |
173 | | function updatedAtTime(Props memory props) internal pure returns (uint256) {
174 | | return props.numbers.updatedAtTime;
175 | | }
176 | |
177 | | function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
178 | | props.numbers.updatedAtTime = value;
179 | | }
180 | |
181 | | function executionFee(Props memory props) internal pure returns (uint256) {
182 | | return props.numbers.executionFee;
183 | | }
184 | |
185 | | function setExecutionFee(Props memory props, uint256 value) internal pure {
186 | | props.numbers.executionFee = value;
187 | | }
188 | |
189 | | function callbackGasLimit(Props memory props) internal pure returns (uint256) {
190 | | return props.numbers.callbackGasLimit;
191 | | }
192 | |
193 | | function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
194 | | props.numbers.callbackGasLimit = value;
195 | | }
196 | |
197 | | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {
198 | | return props.flags.shouldUnwrapNativeToken;
199 | | }
200 | |
201 | | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {
202 | | props.flags.shouldUnwrapNativeToken = value;
203 | | }
204 | | }
205 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./GlvDeposit.sol";
10 | | import "../pricing/ISwapPricingUtils.sol";
11 | |
12 | * | library GlvDepositEventUtils {
13 | | using GlvDeposit for GlvDeposit.Props;
14 | |
15 | | using EventUtils for EventUtils.AddressItems;
16 | | using EventUtils for EventUtils.UintItems;
17 | | using EventUtils for EventUtils.IntItems;
18 | | using EventUtils for EventUtils.BoolItems;
19 | | using EventUtils for EventUtils.Bytes32Items;
20 | | using EventUtils for EventUtils.BytesItems;
21 | | using EventUtils for EventUtils.StringItems;
22 | |
23 | | function emitGlvDepositCreated(
24 | | EventEmitter eventEmitter,
25 | | bytes32 key,
26 | | GlvDeposit.Props memory glvDeposit
27 | | ) internal {
28 | | EventUtils.EventLogData memory eventData;
29 | |
30 | | eventData.addressItems.initItems(7);
31 | | eventData.addressItems.setItem(0, "account", glvDeposit.account());
32 | | eventData.addressItems.setItem(1, "receiver", glvDeposit.receiver());
33 | | eventData.addressItems.setItem(2, "callbackContract", glvDeposit.callbackContract());
34 | | eventData.addressItems.setItem(3, "market", glvDeposit.market());
35 | | eventData.addressItems.setItem(4, "glv", glvDeposit.glv());
36 | | eventData.addressItems.setItem(5, "initialLongToken", glvDeposit.initialLongToken());
37 | | eventData.addressItems.setItem(6, "initialShortToken", glvDeposit.initialShortToken());
38 | |
39 | | eventData.addressItems.initArrayItems(2);
40 | | eventData.addressItems.setItem(0, "longTokenSwapPath", glvDeposit.longTokenSwapPath());
41 | | eventData.addressItems.setItem(1, "shortTokenSwapPath", glvDeposit.shortTokenSwapPath());
42 | |
43 | | eventData.uintItems.initItems(7);
44 | | eventData.uintItems.setItem(0, "initialLongTokenAmount", glvDeposit.initialLongTokenAmount());
45 | | eventData.uintItems.setItem(1, "initialShortTokenAmount", glvDeposit.initialShortTokenAmount());
46 | | eventData.uintItems.setItem(2, "minGlvTokens", glvDeposit.minGlvTokens());
47 | | eventData.uintItems.setItem(3, "updatedAtBlock", glvDeposit.updatedAtBlock());
48 | | eventData.uintItems.setItem(4, "updatedAtTime", glvDeposit.updatedAtTime());
49 | | eventData.uintItems.setItem(5, "executionFee", glvDeposit.executionFee());
50 | | eventData.uintItems.setItem(6, "callbackGasLimit", glvDeposit.callbackGasLimit());
51 | |
52 | | eventData.boolItems.initItems(1);
53 | | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", glvDeposit.shouldUnwrapNativeToken());
54 | |
55 | | eventData.bytes32Items.initItems(1);
56 | | eventData.bytes32Items.setItem(0, "key", key);
57 | |
58 | | eventEmitter.emitEventLog2(
59 | | "GlvDepositCreated",
60 | | key,
61 | | Cast.toBytes32(glvDeposit.account()),
62 | | eventData
63 | | );
64 | | }
65 | |
66 | | function emitGlvDepositExecuted(
67 | | EventEmitter eventEmitter,
68 | | bytes32 key,
69 | | address account,
70 | | uint256 receivedMarketTokens
71 | | ) internal {
72 | | EventUtils.EventLogData memory eventData;
73 | |
74 | | eventData.bytes32Items.initItems(1);
75 | | eventData.bytes32Items.setItem(0, "key", key);
76 | |
77 | | eventData.addressItems.initItems(1);
78 | | eventData.addressItems.setItem(0, "account", account);
79 | |
80 | | eventData.uintItems.initItems(1);
81 | | eventData.uintItems.setItem(2, "receivedMarketTokens", receivedMarketTokens);
82 | |
83 | | eventEmitter.emitEventLog2(
84 | | "GlvDepositExecuted",
85 | | key,
86 | | Cast.toBytes32(account),
87 | | eventData
88 | | );
89 | | }
90 | |
91 | | function emitGlvDepositCancelled(
92 | | EventEmitter eventEmitter,
93 | | bytes32 key,
94 | | address account,
95 | | string memory reason,
96 | | bytes memory reasonBytes
97 | | ) internal {
98 | | EventUtils.EventLogData memory eventData;
99 | |
100 | | eventData.bytes32Items.initItems(1);
101 | | eventData.bytes32Items.setItem(0, "key", key);
102 | |
103 | | eventData.addressItems.initItems(1);
104 | | eventData.addressItems.setItem(0, "account", account);
105 | |
106 | | eventData.stringItems.initItems(1);
107 | | eventData.stringItems.setItem(0, "reason", reason);
108 | |
109 | | eventData.bytesItems.initItems(1);
110 | | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
111 | |
112 | | eventEmitter.emitEventLog2(
113 | | "GlvDepositCancelled",
114 | | key,
115 | | Cast.toBytes32(account),
116 | | eventData
117 | | );
118 | | }
119 | | }
120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./GlvDeposit.sol";
9 | |
10 | | /**
11 | | * @title GlvDepositStoreUtils
12 | | * @dev Library for deposit storage functions
13 | | */
14 | * | library GlvDepositStoreUtils {
15 | | using GlvDeposit for GlvDeposit.Props;
16 | |
17 | | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
18 | | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER"));
19 | | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
20 | | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
21 | | bytes32 internal constant GLV = keccak256(abi.encode("GLV"));
22 | | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET"));
23 | | bytes32 internal constant INITIAL_LONG_TOKEN = keccak256(abi.encode("INITIAL_LONG_TOKEN"));
24 | | bytes32 internal constant INITIAL_SHORT_TOKEN = keccak256(abi.encode("INITIAL_SHORT_TOKEN"));
25 | | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH"));
26 | | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH"));
27 | |
28 | | bytes32 internal constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_LONG_TOKEN_AMOUNT"));
29 | | bytes32 internal constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_SHORT_TOKEN_AMOUNT"));
30 | | bytes32 internal constant MIN_GLV_TOKENS = keccak256(abi.encode("MIN_GLV_TOKENS"));
31 | | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
32 | | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME"));
33 | | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
34 | | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
35 | |
36 | | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
37 | |
38 | | function get(DataStore dataStore, bytes32 key) internal view returns (GlvDeposit.Props memory) {
39 | | GlvDeposit.Props memory deposit;
40 | | if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) {
41 | | return deposit;
42 | | }
43 | |
44 | | deposit.setAccount(dataStore.getAddress(
45 | | keccak256(abi.encode(key, ACCOUNT))
46 | | ));
47 | |
48 | | deposit.setReceiver(dataStore.getAddress(
49 | | keccak256(abi.encode(key, RECEIVER))
50 | | ));
51 | |
52 | | deposit.setCallbackContract(dataStore.getAddress(
53 | | keccak256(abi.encode(key, CALLBACK_CONTRACT))
54 | | ));
55 | |
56 | | deposit.setUiFeeReceiver(dataStore.getAddress(
57 | | keccak256(abi.encode(key, UI_FEE_RECEIVER))
58 | | ));
59 | |
60 | | deposit.setGlv(dataStore.getAddress(
61 | | keccak256(abi.encode(key, GLV))
62 | | ));
63 | |
64 | | deposit.setMarket(dataStore.getAddress(
65 | | keccak256(abi.encode(key, MARKET))
66 | | ));
67 | |
68 | | deposit.setInitialLongToken(dataStore.getAddress(
69 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN))
70 | | ));
71 | |
72 | | deposit.setInitialShortToken(dataStore.getAddress(
73 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))
74 | | ));
75 | |
76 | | deposit.setLongTokenSwapPath(dataStore.getAddressArray(
77 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
78 | | ));
79 | |
80 | | deposit.setShortTokenSwapPath(dataStore.getAddressArray(
81 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
82 | | ));
83 | |
84 | | deposit.setInitialLongTokenAmount(dataStore.getUint(
85 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))
86 | | ));
87 | |
88 | | deposit.setInitialShortTokenAmount(dataStore.getUint(
89 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))
90 | | ));
91 | |
92 | | deposit.setMinGlvTokens(dataStore.getUint(
93 | | keccak256(abi.encode(key, MIN_GLV_TOKENS))
94 | | ));
95 | |
96 | | deposit.setUpdatedAtBlock(dataStore.getUint(
97 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
98 | | ));
99 | |
100 | | deposit.setUpdatedAtTime(dataStore.getUint(
101 | | keccak256(abi.encode(key, UPDATED_AT_TIME))
102 | | ));
103 | |
104 | | deposit.setExecutionFee(dataStore.getUint(
105 | | keccak256(abi.encode(key, EXECUTION_FEE))
106 | | ));
107 | |
108 | | deposit.setCallbackGasLimit(dataStore.getUint(
109 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
110 | | ));
111 | |
112 | | deposit.setShouldUnwrapNativeToken(dataStore.getBool(
113 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
114 | | ));
115 | |
116 | | return deposit;
117 | | }
118 | |
119 | | function set(DataStore dataStore, bytes32 key, GlvDeposit.Props memory glvDeposit) internal {
120 | | dataStore.addBytes32(
121 | | Keys.GLV_DEPOSIT_LIST,
122 | | key
123 | | );
124 | |
125 | | dataStore.addBytes32(
126 | | Keys.accountGlvDepositListKey(glvDeposit.account()),
127 | | key
128 | | );
129 | |
130 | | dataStore.setAddress(
131 | | keccak256(abi.encode(key, ACCOUNT)),
132 | | glvDeposit.account()
133 | | );
134 | |
135 | | dataStore.setAddress(
136 | | keccak256(abi.encode(key, RECEIVER)),
137 | | glvDeposit.receiver()
138 | | );
139 | |
140 | | dataStore.setAddress(
141 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)),
142 | | glvDeposit.callbackContract()
143 | | );
144 | |
145 | | dataStore.setAddress(
146 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)),
147 | | glvDeposit.uiFeeReceiver()
148 | | );
149 | |
150 | | dataStore.setAddress(
151 | | keccak256(abi.encode(key, GLV)),
152 | | glvDeposit.glv()
153 | | );
154 | |
155 | | dataStore.setAddress(
156 | | keccak256(abi.encode(key, MARKET)),
157 | | glvDeposit.market()
158 | | );
159 | |
160 | | dataStore.setAddress(
161 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)),
162 | | glvDeposit.initialLongToken()
163 | | );
164 | |
165 | | dataStore.setAddress(
166 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)),
167 | | glvDeposit.initialShortToken()
168 | | );
169 | |
170 | | dataStore.setAddressArray(
171 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),
172 | | glvDeposit.longTokenSwapPath()
173 | | );
174 | |
175 | | dataStore.setAddressArray(
176 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),
177 | | glvDeposit.shortTokenSwapPath()
178 | | );
179 | |
180 | | dataStore.setUint(
181 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)),
182 | | glvDeposit.initialLongTokenAmount()
183 | | );
184 | |
185 | | dataStore.setUint(
186 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)),
187 | | glvDeposit.initialShortTokenAmount()
188 | | );
189 | |
190 | | dataStore.setUint(
191 | | keccak256(abi.encode(key, MIN_GLV_TOKENS)),
192 | | glvDeposit.minGlvTokens()
193 | | );
194 | |
195 | | dataStore.setUint(
196 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
197 | | glvDeposit.updatedAtBlock()
198 | | );
199 | |
200 | | dataStore.setUint(
201 | | keccak256(abi.encode(key, UPDATED_AT_TIME)),
202 | | glvDeposit.updatedAtTime()
203 | | );
204 | |
205 | | dataStore.setUint(
206 | | keccak256(abi.encode(key, EXECUTION_FEE)),
207 | | glvDeposit.executionFee()
208 | | );
209 | |
210 | | dataStore.setUint(
211 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
212 | | glvDeposit.callbackGasLimit()
213 | | );
214 | |
215 | | dataStore.setBool(
216 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
217 | | glvDeposit.shouldUnwrapNativeToken()
218 | | );
219 | | }
220 | |
221 | | function remove(DataStore dataStore, bytes32 key, address account) internal {
222 | | if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) {
223 | | revert Errors.GlvDepositNotFound(key);
224 | | }
225 | |
226 | | dataStore.removeBytes32(
227 | | Keys.GLV_DEPOSIT_LIST,
228 | | key
229 | | );
230 | |
231 | | dataStore.removeBytes32(
232 | | Keys.accountGlvDepositListKey(account),
233 | | key
234 | | );
235 | |
236 | | dataStore.removeAddress(
237 | | keccak256(abi.encode(key, ACCOUNT))
238 | | );
239 | |
240 | | dataStore.removeAddress(
241 | | keccak256(abi.encode(key, RECEIVER))
242 | | );
243 | |
244 | | dataStore.removeAddress(
245 | | keccak256(abi.encode(key, CALLBACK_CONTRACT))
246 | | );
247 | |
248 | | dataStore.removeAddress(
249 | | keccak256(abi.encode(key, UI_FEE_RECEIVER))
250 | | );
251 | |
252 | | dataStore.removeAddress(
253 | | keccak256(abi.encode(key, GLV))
254 | | );
255 | |
256 | | dataStore.removeAddress(
257 | | keccak256(abi.encode(key, MARKET))
258 | | );
259 | |
260 | | dataStore.removeAddress(
261 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN))
262 | | );
263 | |
264 | | dataStore.removeAddress(
265 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN))
266 | | );
267 | |
268 | | dataStore.removeAddressArray(
269 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
270 | | );
271 | |
272 | | dataStore.removeAddressArray(
273 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
274 | | );
275 | |
276 | | dataStore.removeUint(
277 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT))
278 | | );
279 | |
280 | | dataStore.removeUint(
281 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT))
282 | | );
283 | |
284 | | dataStore.removeUint(
285 | | keccak256(abi.encode(key, MIN_GLV_TOKENS))
286 | | );
287 | |
288 | | dataStore.removeUint(
289 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
290 | | );
291 | |
292 | | dataStore.removeUint(
293 | | keccak256(abi.encode(key, UPDATED_AT_TIME))
294 | | );
295 | |
296 | | dataStore.removeUint(
297 | | keccak256(abi.encode(key, EXECUTION_FEE))
298 | | );
299 | |
300 | | dataStore.removeUint(
301 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
302 | | );
303 | |
304 | | dataStore.removeBool(
305 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
306 | | );
307 | | }
308 | |
309 | | function getGlvDepositCount(DataStore dataStore) internal view returns (uint256) {
310 | | return dataStore.getBytes32Count(Keys.GLV_DEPOSIT_LIST);
311 | | }
312 | |
313 | | function getGlvDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
314 | | return dataStore.getBytes32ValuesAt(Keys.GLV_DEPOSIT_LIST, start, end);
315 | | }
316 | |
317 | | function getAccountGlvDepositCount(DataStore dataStore, address account) internal view returns (uint256) {
318 | | return dataStore.getBytes32Count(Keys.accountGlvDepositListKey(account));
319 | | }
320 | |
321 | | function getAccountGlvDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
322 | | return dataStore.getBytes32ValuesAt(Keys.accountGlvDepositListKey(account), start, end);
323 | | }
324 | | }
325 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../glv/Glv.sol";
6 | | import "../glv/GlvVault.sol";
7 | | import "../glv/GlvUtils.sol";
8 | | import "../glv/GlvDeposit.sol";
9 | | import "../glv/GlvDepositEventUtils.sol";
10 | | import "../glv/GlvDepositStoreUtils.sol";
11 | | import "../feature/FeatureUtils.sol";
12 | | import "../deposit/DepositVault.sol";
13 | | import "../deposit/ExecuteDepositUtils.sol";
14 | | import "../deposit/DepositUtils.sol";
15 | | import "../data/DataStore.sol";
16 | | import "../oracle/Oracle.sol";
17 | | import "../market/Market.sol";
18 | | import "../market/MarketUtils.sol";
19 | | import "../data/Keys.sol";
20 | | import "../event/EventUtils.sol";
21 | |
22 | * | library GlvDepositUtils {
23 | | using GlvDeposit for GlvDeposit.Props;
24 | | using Deposit for Deposit.Props;
25 | | using SafeCast for int256;
26 | | using EventUtils for EventUtils.UintItems;
27 | |
28 | | struct CreateGlvDepositParams {
29 | | address glv;
30 | | address receiver;
31 | | address callbackContract;
32 | | address uiFeeReceiver;
33 | | address market;
34 | | address initialLongToken;
35 | | address initialShortToken;
36 | | address[] longTokenSwapPath;
37 | | address[] shortTokenSwapPath;
38 | | uint256 minGlvTokens;
39 | | bool shouldUnwrapNativeToken;
40 | | uint256 executionFee;
41 | | uint256 callbackGasLimit;
42 | | }
43 | |
44 | | struct ExecuteGlvDepositParams {
45 | | DataStore dataStore;
46 | | EventEmitter eventEmitter;
47 | | GlvVault glvVault;
48 | | Oracle oracle;
49 | | bytes32 key;
50 | | uint256 startingGas;
51 | | address keeper;
52 | | }
53 | |
54 | | struct ExecuteGlvDepositCache {
55 | | uint256 requestExpirationTime;
56 | | uint256 maxOracleTimestamp;
57 | | uint256 receivedMarketTokens;
58 | | uint256 mintAmount;
59 | | uint256 marketCount;
60 | | uint256 oraclePriceCount;
61 | | }
62 | |
63 | | function createGlvDeposit(
64 | | DataStore dataStore,
65 | | EventEmitter eventEmitter,
66 | | GlvVault glvVault,
67 | | address account,
68 | | CreateGlvDepositParams memory params
69 | | ) internal returns (bytes32) {
70 | | AccountUtils.validateAccount(account);
71 | | GlvUtils.validateGlv(dataStore, params.glv);
72 | | GlvUtils.validateMarket(dataStore, params.glv, params.market, true);
73 | |
74 | | MarketUtils.validateEnabledMarket(dataStore, params.market);
75 | | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath);
76 | | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath);
77 | |
78 | | if (params.initialLongToken == params.market) {
79 | | // user deposited GM tokens
80 | | if (params.initialShortToken != address(0)) {
81 | | revert Errors.InvalidGlvDepositInitialShortToken(params.initialLongToken, params.initialShortToken);
82 | | }
83 | | if (params.longTokenSwapPath.length > 0 || params.longTokenSwapPath.length > 0) {
84 | | revert Errors.InvalidGlvDepositSwapPath(
85 | | params.longTokenSwapPath.length,
86 | | params.longTokenSwapPath.length
87 | | );
88 | | }
89 | | }
90 | |
91 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would
92 | | // be non-zero, the initialShortTokenAmount would be zero
93 | | uint256 initialLongTokenAmount = glvVault.recordTransferIn(params.initialLongToken);
94 | | uint256 initialShortTokenAmount;
95 | | if (params.initialShortToken != address(0)) {
96 | | // initialShortToken could be zero address if user deposits GM token
97 | | initialShortTokenAmount = glvVault.recordTransferIn(params.initialShortToken);
98 | | }
99 | |
100 | | address wnt = TokenUtils.wnt(dataStore);
101 | | if (params.initialLongToken == wnt) {
102 | | initialLongTokenAmount -= params.executionFee;
103 | | } else if (params.initialShortToken == wnt) {
104 | | initialShortTokenAmount -= params.executionFee;
105 | | } else {
106 | | uint256 wntAmount = glvVault.recordTransferIn(wnt);
107 | | if (wntAmount < params.executionFee) {
108 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee);
109 | | }
110 | |
111 | | params.executionFee = wntAmount;
112 | | }
113 | |
114 | | if (initialLongTokenAmount == 0 && initialShortTokenAmount == 0) {
115 | | revert Errors.EmptyGlvDepositAmounts();
116 | | }
117 | |
118 | | AccountUtils.validateReceiver(params.receiver);
119 | |
120 | | GlvDeposit.Props memory glvDeposit = GlvDeposit.Props(
121 | | GlvDeposit.Addresses({
122 | | account: account,
123 | | glv: params.glv,
124 | | receiver: params.receiver,
125 | | callbackContract: params.callbackContract,
126 | | uiFeeReceiver: params.uiFeeReceiver,
127 | | market: params.market,
128 | | initialLongToken: params.initialLongToken,
129 | | initialShortToken: params.initialShortToken,
130 | | longTokenSwapPath: params.longTokenSwapPath,
131 | | shortTokenSwapPath: params.shortTokenSwapPath
132 | | }),
133 | | GlvDeposit.Numbers({
134 | | initialLongTokenAmount: initialLongTokenAmount,
135 | | initialShortTokenAmount: initialShortTokenAmount,
136 | | minGlvTokens: params.minGlvTokens,
137 | | updatedAtBlock: Chain.currentBlockNumber(),
138 | | updatedAtTime: Chain.currentTimestamp(),
139 | | executionFee: params.executionFee,
140 | | callbackGasLimit: params.callbackGasLimit
141 | | }),
142 | | GlvDeposit.Flags({shouldUnwrapNativeToken: params.shouldUnwrapNativeToken})
143 | | );
144 | |
145 | | CallbackUtils.validateCallbackGasLimit(dataStore, params.callbackGasLimit);
146 | |
147 | | uint256 marketCount = GlvUtils.getMarketCount(dataStore, glvDeposit.glv());
148 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvDepositGasLimit(dataStore, glvDeposit, marketCount);
149 | | uint256 oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount(
150 | | marketCount,
151 | | params.longTokenSwapPath.length + params.shortTokenSwapPath.length
152 | | );
153 | | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount);
154 | |
155 | | bytes32 key = NonceUtils.getNextKey(dataStore);
156 | |
157 | | GlvDepositStoreUtils.set(dataStore, key, glvDeposit);
158 | |
159 | | GlvDepositEventUtils.emitGlvDepositCreated(eventEmitter, key, glvDeposit);
160 | |
161 | | return key;
162 | | }
163 | |
164 | | function executeGlvDeposit(
165 | | ExecuteGlvDepositParams memory params,
166 | | GlvDeposit.Props memory glvDeposit
167 | | ) internal returns (uint256) {
168 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
169 | | params.startingGas -= gasleft() / 63;
170 | |
171 | | GlvDepositStoreUtils.remove(params.dataStore, params.key, glvDeposit.account());
172 | |
173 | | if (glvDeposit.account() == address(0)) {
174 | | revert Errors.EmptyGlvDeposit();
175 | | }
176 | |
177 | | if (params.oracle.minTimestamp() < glvDeposit.updatedAtTime()) {
178 | | revert Errors.OracleTimestampsAreSmallerThanRequired(
179 | | params.oracle.minTimestamp(),
180 | | glvDeposit.updatedAtTime()
181 | | );
182 | | }
183 | |
184 | | ExecuteGlvDepositCache memory cache;
185 | |
186 | | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
187 | | cache.maxOracleTimestamp = params.oracle.maxTimestamp();
188 | |
189 | | if (cache.maxOracleTimestamp > glvDeposit.updatedAtTime() + cache.requestExpirationTime) {
190 | | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
191 | | cache.maxOracleTimestamp,
192 | | glvDeposit.updatedAtTime(),
193 | | cache.requestExpirationTime
194 | | );
195 | | }
196 | |
197 | | cache.receivedMarketTokens = _processMarketDeposit(params, glvDeposit);
198 | | cache.mintAmount = _getMintAmount(params.dataStore, params.oracle, glvDeposit, cache.receivedMarketTokens);
199 | |
200 | | if (cache.mintAmount < glvDeposit.minGlvTokens()) {
201 | | revert Errors.MinMarketTokens(cache.mintAmount, glvDeposit.minGlvTokens());
202 | | }
203 | |
204 | | Glv(payable(glvDeposit.glv())).mint(glvDeposit.receiver(), cache.mintAmount);
205 | |
206 | | GlvDepositEventUtils.emitGlvDepositExecuted(
207 | | params.eventEmitter,
208 | | params.key,
209 | | glvDeposit.account(),
210 | | cache.mintAmount
211 | | );
212 | |
213 | | cache.marketCount = GlvUtils.getMarketCount(params.dataStore, glvDeposit.glv());
214 | | cache.oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount(
215 | | cache.marketCount,
216 | | glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length
217 | | );
218 | | GasUtils.payExecutionFee(
219 | | params.dataStore,
220 | | params.eventEmitter,
221 | | params.glvVault,
222 | | params.key,
223 | | glvDeposit.callbackContract(),
224 | | glvDeposit.executionFee(),
225 | | params.startingGas,
226 | | cache.oraclePriceCount,
227 | | params.keeper,
228 | | glvDeposit.receiver()
229 | | );
230 | |
231 | | EventUtils.EventLogData memory eventData;
232 | | eventData.uintItems.initItems(1);
233 | | eventData.uintItems.setItem(0, "receivedGlvTokens", cache.mintAmount);
234 | | CallbackUtils.afterGlvDepositExecution(params.key, glvDeposit, eventData);
235 | |
236 | | return cache.mintAmount;
237 | | }
238 | |
239 | | function _getMintAmount(
240 | | DataStore dataStore,
241 | | Oracle oracle,
242 | | GlvDeposit.Props memory glvDeposit,
243 | | uint256 receivedMarketTokens
244 | | ) internal view returns (uint256) {
245 | | Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, glvDeposit.market());
246 | | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
247 | | dataStore,
248 | | market,
249 | | oracle.getPrimaryPrice(market.indexToken),
250 | | oracle.getPrimaryPrice(market.longToken),
251 | | oracle.getPrimaryPrice(market.shortToken),
252 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
253 | | false // maximize
254 | | );
255 | | uint256 receivedMarketTokensUsd = MarketUtils.marketTokenAmountToUsd(
256 | | receivedMarketTokens,
257 | | poolValueInfo.poolValue.toUint256(),
258 | | ERC20(market.marketToken).totalSupply()
259 | | );
260 | |
261 | | Glv glv = Glv(payable(glvDeposit.glv()));
262 | | uint256 glvValue = GlvUtils.getValue(dataStore, oracle, glv);
263 | | uint256 glvSupply = glv.totalSupply();
264 | | return GlvUtils.usdToGlvTokenAmount(receivedMarketTokensUsd, glvValue, glvSupply);
265 | | }
266 | |
267 | | function _processMarketDeposit(
268 | | ExecuteGlvDepositParams memory params,
269 | | GlvDeposit.Props memory glvDeposit
270 | | ) private returns (uint256) {
271 | | if (glvDeposit.market() == glvDeposit.initialLongToken()) {
272 | | // user deposited GM tokens
273 | | return glvDeposit.initialLongTokenAmount();
274 | | }
275 | |
276 | | Deposit.Props memory deposit = Deposit.Props(
277 | | Deposit.Addresses({
278 | | account: glvDeposit.account(),
279 | | receiver: glvDeposit.receiver(),
280 | | callbackContract: address(0),
281 | | uiFeeReceiver: glvDeposit.uiFeeReceiver(),
282 | | market: glvDeposit.market(),
283 | | initialLongToken: glvDeposit.initialLongToken(),
284 | | initialShortToken: glvDeposit.initialShortToken(),
285 | | longTokenSwapPath: new address[](0),
286 | | shortTokenSwapPath: new address[](0)
287 | | }),
288 | | Deposit.Numbers({
289 | | initialLongTokenAmount: glvDeposit.initialLongTokenAmount(),
290 | | initialShortTokenAmount: glvDeposit.initialShortTokenAmount(),
291 | | minMarketTokens: 0,
292 | | updatedAtBlock: 0,
293 | | updatedAtTime: glvDeposit.updatedAtTime(),
294 | | executionFee: 0,
295 | | callbackGasLimit: 0
296 | | }),
297 | | Deposit.Flags({shouldUnwrapNativeToken: false})
298 | | );
299 | |
300 | | bytes32 depositKey = NonceUtils.getNextKey(params.dataStore);
301 | | params.dataStore.addBytes32(Keys.DEPOSIT_LIST, depositKey);
302 | | DepositEventUtils.emitDepositCreated(params.eventEmitter, depositKey, deposit, DepositUtils.DepositType.Glv);
303 | |
304 | | ExecuteDepositUtils.ExecuteDepositParams memory executeDepositParams = ExecuteDepositUtils.ExecuteDepositParams(
305 | | params.dataStore,
306 | | params.eventEmitter,
307 | | DepositVault(payable(params.glvVault)),
308 | | params.oracle,
309 | | depositKey,
310 | | params.keeper,
311 | | params.startingGas,
312 | | ISwapPricingUtils.SwapPricingType.TwoStep,
313 | | true // includeVirtualInventoryImpact
314 | | );
315 | |
316 | | return ExecuteDepositUtils.executeDeposit(executeDepositParams, deposit);
317 | | }
318 | |
319 | | function cancelGlvDeposit(
320 | | DataStore dataStore,
321 | | EventEmitter eventEmitter,
322 | | GlvVault glvVault,
323 | | bytes32 key,
324 | | address keeper,
325 | | uint256 startingGas,
326 | | string memory reason,
327 | | bytes memory reasonBytes
328 | | ) internal {
329 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
330 | | startingGas -= gasleft() / 63;
331 | |
332 | | GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, key);
333 | | if (glvDeposit.account() == address(0)) {
334 | | revert Errors.EmptyGlvDeposit();
335 | | }
336 | |
337 | | if (glvDeposit.initialLongTokenAmount() == 0 && glvDeposit.initialShortTokenAmount() == 0) {
338 | | revert Errors.EmptyGlvDepositAmounts();
339 | | }
340 | |
341 | | GlvDepositStoreUtils.remove(dataStore, key, glvDeposit.account());
342 | |
343 | | if (glvDeposit.initialLongTokenAmount() > 0) {
344 | | glvVault.transferOut(
345 | | glvDeposit.initialLongToken(),
346 | | glvDeposit.account(),
347 | | glvDeposit.initialLongTokenAmount(),
348 | | glvDeposit.shouldUnwrapNativeToken()
349 | | );
350 | | }
351 | |
352 | | if (glvDeposit.initialShortTokenAmount() > 0) {
353 | | glvVault.transferOut(
354 | | glvDeposit.initialShortToken(),
355 | | glvDeposit.account(),
356 | | glvDeposit.initialShortTokenAmount(),
357 | | glvDeposit.shouldUnwrapNativeToken()
358 | | );
359 | | }
360 | |
361 | | GlvDepositEventUtils.emitGlvDepositCancelled(eventEmitter, key, glvDeposit.account(), reason, reasonBytes);
362 | |
363 | | uint256 marketCount = GlvUtils.getMarketCount(dataStore, glvDeposit.glv());
364 | | GasUtils.payExecutionFee(
365 | | dataStore,
366 | | eventEmitter,
367 | | glvVault,
368 | | key,
369 | | glvDeposit.callbackContract(),
370 | | glvDeposit.executionFee(),
371 | | startingGas,
372 | | GasUtils.estimateGlvDepositOraclePriceCount(
373 | | marketCount,
374 | | glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length
375 | | ),
376 | | keeper,
377 | | glvDeposit.receiver()
378 | | );
379 | |
380 | | EventUtils.EventLogData memory eventData;
381 | | CallbackUtils.afterGlvDepositCancellation(key, glvDeposit, eventData);
382 | | }
383 | | }
384 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../glv/Glv.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../oracle/Oracle.sol";
8 | | import "../market/Market.sol";
9 | | import "../market/MarketUtils.sol";
10 | | import "../shift/ShiftUtils.sol";
11 | | import "../exchange/IShiftHandler.sol";
12 | | import "../market/MarketPoolValueInfo.sol";
13 | |
14 | * | library GlvUtils {
15 | | using SafeCast for int256;
16 | |
17 | | // @dev get the USD value of the Glv
18 | | // @param dataStore DataStore
19 | | // @param oracle Oracle
20 | | // @param glv Glv
21 | | // @return the USD value of the Glv
22 | | function getValue(DataStore dataStore, Oracle oracle, Glv glv) internal view returns (uint256 glvValue) {
23 | | address[] memory markets = new address[](2);
24 | | for (uint256 i = 0; i < markets.length; i++) {
25 | | address marketAddress = markets[i];
26 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
27 | | (int256 marketTokenPrice, ) = MarketUtils.getMarketTokenPrice(
28 | | dataStore,
29 | | market,
30 | | oracle.getPrimaryPrice(market.indexToken),
31 | | oracle.getPrimaryPrice(market.longToken),
32 | | oracle.getPrimaryPrice(market.shortToken),
33 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
34 | | true // maximize
35 | | );
36 | |
37 | | if (marketTokenPrice < 0) {
38 | | revert Errors.InvalidMarketTokenPrice(marketAddress, marketTokenPrice);
39 | | }
40 | |
41 | | uint256 balance = IERC20(marketAddress).balanceOf(address(glv));
42 | |
43 | | glvValue += balance * marketTokenPrice.toUint256();
44 | | }
45 | | }
46 | |
47 | | // @dev convert a USD value to number of glv tokens
48 | | // @param usdValue the input USD value
49 | | // @param glvValue the value of the pool
50 | | // @param supply the supply of glv tokens
51 | | // @return the number of glv tokens
52 | | function usdToGlvTokenAmount(uint256 usdValue, uint256 glvValue, uint256 supply) internal pure returns (uint256) {
53 | | // if the supply and glvValue is zero, use 1 USD as the token price
54 | | if (supply == 0 && glvValue == 0) {
55 | | return Precision.floatToWei(usdValue);
56 | | }
57 | |
58 | | // if the supply is zero and the glvValue is more than zero,
59 | | // then include the glvValue for the amount of tokens minted so that
60 | | // the glv token price after mint would be 1 USD
61 | | // TODO: copy-pasted from MarketUtils, is it correct for glv?
62 | | if (supply == 0 && glvValue > 0) {
63 | | return Precision.floatToWei(glvValue + usdValue);
64 | | }
65 | |
66 | | // round glv tokens down
67 | | return Precision.mulDiv(supply, usdValue, glvValue);
68 | | }
69 | |
70 | | function validateMarket(DataStore dataStore, address glv, address market, bool shouldBeEnabled) internal view {
71 | | if (!dataStore.containsAddress(Keys.glvSupportedMarketListKey(glv), market)) {
72 | | revert Errors.GlvUnsupportedMarket(glv, market);
73 | | }
74 | |
75 | | if (shouldBeEnabled) {
76 | | if (dataStore.getBool(Keys.isGlvMarketDisabledKey(glv, market))) {
77 | | revert Errors.GlvDisabledMarket(glv, market);
78 | | }
79 | | }
80 | | }
81 | |
82 | | function validateGlv(DataStore dataStore, address glv) internal view {
83 | | if (!dataStore.containsAddress(Keys.GLV_LIST, glv)) {
84 | | revert Errors.EmptyGlv(glv);
85 | | }
86 | | }
87 | |
88 | | function getMarketCount(DataStore dataStore, address glv) internal view returns (uint256) {
89 | | return dataStore.getAddressCount(Keys.glvSupportedMarketListKey(glv));
90 | | }
91 | |
92 | | function createShift(
93 | | DataStore dataStore,
94 | | Oracle oracle,
95 | | IShiftHandler shiftHandler,
96 | | ShiftVault shiftVault,
97 | | address account,
98 | | address glv,
99 | | uint256 marketTokenAmount,
100 | | ShiftUtils.CreateShiftParams memory params
101 | | ) internal {
102 | | validateGlv(dataStore, glv);
103 | |
104 | | validateMarket(dataStore, glv, params.fromMarket, false);
105 | | validateMarket(dataStore, glv, params.toMarket, true);
106 | |
107 | | if (params.receiver != address(glv)) {
108 | | revert Errors.GlvInvalidReceiver(address(glv), params.receiver);
109 | | }
110 | | if (params.callbackContract != address(this)) {
111 | | revert Errors.GlvInvalidCallbackContract(address(glv), params.callbackContract);
112 | | }
113 | |
114 | | Market.Props memory fromMarket = MarketStoreUtils.get(dataStore, params.fromMarket);
115 | | uint256 marketTokenBalance = ERC20(fromMarket.marketToken).balanceOf(glv);
116 | | if (marketTokenBalance < marketTokenAmount) {
117 | | revert Errors.GlvInsufficientMarketTokenBalance(
118 | | glv,
119 | | fromMarket.marketToken,
120 | | marketTokenBalance,
121 | | marketTokenAmount
122 | | );
123 | | }
124 | |
125 | | validatePendingShift(dataStore, glv);
126 | |
127 | | Market.Props memory toMarket = MarketStoreUtils.get(dataStore, params.fromMarket);
128 | | validateMaxMarketTokenBalance(dataStore, oracle, glv, toMarket, marketTokenAmount);
129 | |
130 | | TokenUtils.transfer(dataStore, fromMarket.marketToken, address(shiftVault), marketTokenAmount);
131 | | bytes32 shiftKey = shiftHandler.createShift(account, params);
132 | |
133 | | setPendingShift(dataStore, glv, shiftKey);
134 | | }
135 | |
136 | | function validatePendingShift(DataStore dataStore, address glv) internal view {
137 | | bytes32 shiftKey = dataStore.getBytes32(Keys.glvPendingShiftKey(glv));
138 | | if (shiftKey != bytes32(0)) {
139 | | revert Errors.GlvHasPendingShift(glv);
140 | | }
141 | | }
142 | |
143 | | function setPendingShift(DataStore dataStore, address glv, bytes32 shiftKey) internal {
144 | | dataStore.setBytes32(Keys.glvPendingShiftKey(glv), shiftKey);
145 | | dataStore.setAddress(Keys.glvPendingShiftBackrefKey(shiftKey), glv);
146 | | }
147 | |
148 | | function clearPendingShift(DataStore dataStore, bytes32 shiftKey) internal {
149 | | address glv = dataStore.getAddress(Keys.glvPendingShiftBackrefKey(shiftKey));
150 | | if (glv == address(0)) {
151 | | revert Errors.GlvShiftNotFound(shiftKey);
152 | | }
153 | | dataStore.removeAddress(Keys.glvPendingShiftBackrefKey(shiftKey));
154 | | dataStore.removeBytes32(Keys.glvPendingShiftKey(glv));
155 | | }
156 | |
157 | | function validateMaxMarketTokenBalance(
158 | | DataStore dataStore,
159 | | Oracle oracle,
160 | | address glv,
161 | | Market.Props memory market,
162 | | uint256 marketTokenAmount
163 | | ) internal view {
164 | | uint256 maxMarketTokenBalanceUsd = getGlvMaxMarketTokenBalanceUsd(dataStore, glv, market.marketToken);
165 | | if (maxMarketTokenBalanceUsd == 0) {
166 | | return;
167 | | }
168 | |
169 | | MarketPoolValueInfo.Props memory fromMarketPoolValueInfo = MarketUtils.getPoolValueInfo(
170 | | dataStore,
171 | | market,
172 | | oracle.getPrimaryPrice(market.indexToken),
173 | | oracle.getPrimaryPrice(market.longToken),
174 | | oracle.getPrimaryPrice(market.shortToken),
175 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
176 | | true // maximize
177 | | );
178 | |
179 | | uint256 marketTokenSupply = ERC20(market.marketToken).totalSupply();
180 | | uint256 marketTokenUsd = MarketUtils.marketTokenAmountToUsd(
181 | | marketTokenAmount,
182 | | fromMarketPoolValueInfo.poolValue.toUint256(),
183 | | marketTokenSupply
184 | | );
185 | | uint256 marketTokenBalanceUsd = MarketUtils.marketTokenAmountToUsd(
186 | | ERC20(market.marketToken).balanceOf(glv),
187 | | fromMarketPoolValueInfo.poolValue.toUint256(),
188 | | marketTokenSupply
189 | | );
190 | | uint256 nextMarketTokenBalanceUsd = marketTokenBalanceUsd + marketTokenUsd;
191 | | if (nextMarketTokenBalanceUsd > maxMarketTokenBalanceUsd) {
192 | | revert Errors.GlvMaxMarketTokenBalanceExceeded(
193 | | glv,
194 | | market.marketToken,
195 | | maxMarketTokenBalanceUsd,
196 | | nextMarketTokenBalanceUsd
197 | | );
198 | | }
199 | | }
200 | |
201 | | function getGlvMaxMarketTokenBalanceUsd(
202 | | DataStore dataStore,
203 | | address glv,
204 | | address market
205 | | ) internal view returns (uint256) {
206 | | return dataStore.getUint(Keys.glvMaxMarketTokenBalanceUsdKey(glv, market));
207 | | }
208 | |
209 | | function addMarket(DataStore dataStore, address glv, address market) internal {
210 | | GlvUtils.validateGlv(dataStore, glv);
211 | | MarketUtils.validateEnabledMarket(dataStore, market);
212 | |
213 | | bytes32 key = Keys.glvSupportedMarketListKey(glv);
214 | | if (dataStore.containsAddress(key, market)) {
215 | | revert Errors.GlvMarketAlreadyExists(glv, market);
216 | | }
217 | | dataStore.addAddress(key, market);
218 | | }
219 | |
220 | | function disableMarket(DataStore dataStore, address glv, address market) internal {
221 | | GlvUtils.validateGlv(dataStore, glv);
222 | | bytes32 key = Keys.glvSupportedMarketListKey(glv);
223 | | if (!dataStore.containsAddress(key, market)) {
224 | | revert Errors.GlvUnsupportedMarket(glv, market);
225 | | }
226 | |
227 | | dataStore.setBool(Keys.isGlvMarketDisabledKey(glv, market), true);
228 | | }
229 | | }
230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvVault.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../bank/StrictBank.sol";
6 | |
7 | * | contract GlvVault is StrictBank {
8 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
9 | | }
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/GovTimelockController.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/governance/TimelockController.sol";
6 | |
7 | * | contract GovTimelockController is TimelockController {
8 | | string private _name;
9 | |
10 | | constructor(
11 | | string memory name_,
12 | | uint256 minDelay,
13 | | address[] memory proposers,
14 | | address[] memory executors,
15 | | address admin
16 | | ) TimelockController(minDelay, proposers, executors, admin) {
17 | | _name = name_;
18 | | }
19 | |
20 | | function name() public view returns (string memory) {
21 | | return _name;
22 | | }
23 | | }
24 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/GovToken.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
7 | | import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
8 | |
9 | | import "../chain/Chain.sol";
10 | | import "../role/RoleModule.sol";
11 | |
12 | * | contract GovToken is ERC20, ERC20Permit, ERC20Votes, RoleModule {
13 | | uint8 private _decimals;
14 | |
15 | | constructor(
16 | | RoleStore roleStore_,
17 | | string memory name_,
18 | | string memory symbol_,
19 | | uint8 decimals_
20 | | )
21 | | ERC20(name_, symbol_)
22 | | ERC20Permit(name_)
23 | | RoleModule(roleStore_)
24 | | {
25 | | _decimals = decimals_;
26 | | }
27 | |
28 | | function clock() public view override returns (uint48) {
29 | | return SafeCast.toUint48(Chain.currentTimestamp());
30 | | }
31 | |
32 | | // solhint-disable-next-line func-name-mixedcase
33 | | function CLOCK_MODE() public view override returns (string memory) {
34 | | // Check that the clock was not modified
35 | | require(clock() == Chain.currentTimestamp(), "ERC20Votes: broken clock mode");
36 | | return "mode=timestamp";
37 | | }
38 | |
39 | | function decimals() public view override returns (uint8) {
40 | | return _decimals;
41 | | }
42 | |
43 | | // @dev mint tokens to an account
44 | | // @param account the account to mint to
45 | | // @param amount the amount of tokens to mint
46 | | function mint(address account, uint256 amount) external onlyGovTokenController {
47 | | _mint(account, amount);
48 | | }
49 | |
50 | | // @dev burn tokens from an account
51 | | // @param account the account to burn tokens for
52 | | // @param amount the amount of tokens to burn
53 | | function burn(address account, uint256 amount) external onlyGovTokenController {
54 | | _burn(account, amount);
55 | | }
56 | |
57 | | function _transfer(address from, address to, uint256 amount) internal override {
58 | | // only allow GOV_TOKEN_CONTROLLERs to make transfers
59 | | // the user would need to approve the GOV_TOKEN_CONTROLLER contract
60 | | // the GOV_TOKEN_CONTROLLER contract can then call transferFrom to transfer tokens
61 | | _validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER");
62 | |
63 | | super._transfer(from, to, amount);
64 | | }
65 | |
66 | | // The functions below are overrides required by Solidity.
67 | |
68 | | function _afterTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) {
69 | | super._afterTokenTransfer(from, to, amount);
70 | | }
71 | |
72 | | function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {
73 | | super._mint(to, amount);
74 | | }
75 | |
76 | | function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {
77 | | super._burn(account, amount);
78 | | }
79 | | }
80 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/ProtocolGovernor.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/governance/Governor.sol";
6 | | import "@openzeppelin/contracts/governance/compatibility/GovernorCompatibilityBravo.sol";
7 | | import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
8 | | import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
9 | | import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
10 | | import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
11 | |
12 | | import "../chain/Chain.sol";
13 | |
14 | * | contract ProtocolGovernor is
15 | | Governor,
16 | | GovernorSettings,
17 | | GovernorCompatibilityBravo,
18 | | GovernorVotes,
19 | | GovernorVotesQuorumFraction,
20 | | GovernorTimelockControl
21 | | {
22 | |
23 | | string private _version;
24 | |
25 | | constructor(
26 | | IVotes token_,
27 | | TimelockController timelock_,
28 | | string memory name_,
29 | | string memory version_,
30 | | uint256 votingDelay_,
31 | | uint256 votingPeriod_,
32 | | uint256 proposalThreshold_,
33 | | uint256 quorumNumeratorValue_
34 | | )
35 | | Governor(name_)
36 | | GovernorVotes(token_)
37 | | GovernorSettings(votingDelay_, votingPeriod_, proposalThreshold_)
38 | | GovernorVotesQuorumFraction(quorumNumeratorValue_)
39 | | GovernorTimelockControl(timelock_)
40 | | {
41 | | _version = version_;
42 | | }
43 | |
44 | | function clock() public view override(GovernorVotes, IGovernor) returns (uint48) {
45 | | return SafeCast.toUint48(Chain.currentTimestamp());
46 | | }
47 | |
48 | | // solhint-disable-next-line func-name-mixedcase
49 | | function CLOCK_MODE() public view override(GovernorVotes, IGovernor) returns (string memory) {
50 | | // Check that the clock was not modified
51 | | require(clock() == Chain.currentTimestamp(), "ERC20Votes: broken clock mode");
52 | | return "mode=timestamp";
53 | | }
54 | |
55 | | function version() public view override(Governor, IGovernor) returns (string memory) {
56 | | return _version;
57 | | }
58 | |
59 | | // The functions below are overrides required by Solidity.
60 | |
61 | | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
62 | | return super.proposalThreshold();
63 | | }
64 | |
65 | | function state(
66 | | uint256 proposalId
67 | | ) public view override(Governor, IGovernor, GovernorTimelockControl) returns (ProposalState) {
68 | | return super.state(proposalId);
69 | | }
70 | |
71 | | function propose(
72 | | address[] memory targets,
73 | | uint256[] memory values,
74 | | bytes[] memory calldatas,
75 | | string memory description
76 | | ) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) {
77 | | return super.propose(targets, values, calldatas, description);
78 | | }
79 | |
80 | | function cancel(
81 | | address[] memory targets,
82 | | uint256[] memory values,
83 | | bytes[] memory calldatas,
84 | | bytes32 descriptionHash
85 | | ) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) {
86 | | return super.cancel(targets, values, calldatas, descriptionHash);
87 | | }
88 | |
89 | | function _execute(
90 | | uint256 proposalId,
91 | | address[] memory targets,
92 | | uint256[] memory values,
93 | | bytes[] memory calldatas,
94 | | bytes32 descriptionHash
95 | | ) internal override(Governor, GovernorTimelockControl) {
96 | | super._execute(proposalId, targets, values, calldatas, descriptionHash);
97 | | }
98 | |
99 | | function _cancel(
100 | | address[] memory targets,
101 | | uint256[] memory values,
102 | | bytes[] memory calldatas,
103 | | bytes32 descriptionHash
104 | | ) internal override(Governor, GovernorTimelockControl) returns (uint256) {
105 | | return super._cancel(targets, values, calldatas, descriptionHash);
106 | | }
107 | |
108 | | function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
109 | | return super._executor();
110 | | }
111 | |
112 | | function supportsInterface(
113 | | bytes4 interfaceId
114 | | ) public view override(Governor, IERC165, GovernorTimelockControl) returns (bool) {
115 | | return super.supportsInterface(interfaceId);
116 | | }
117 | | }
118 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/liquidation/LiquidationUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../position/PositionUtils.sol";
6 | | import "../position/PositionStoreUtils.sol";
7 | | import "../order/OrderStoreUtils.sol";
8 | | import "../order/OrderEventUtils.sol";
9 | | import "../nonce/NonceUtils.sol";
10 | | import "../callback/CallbackUtils.sol";
11 | |
12 | | // @title LiquidationUtils
13 | | // @dev Library to help with liquidations
14 | * | library LiquidationUtils {
15 | | using Position for Position.Props;
16 | | using Order for Order.Props;
17 | |
18 | | // @dev creates a liquidation order for a position
19 | | // @param dataStore DataStore
20 | | // @param account the position's account
21 | | // @param market the position's market
22 | | // @param collateralToken the position's collateralToken
23 | | // @param isLong whether the position is long or short
24 | * | function createLiquidationOrder(
25 | | DataStore dataStore,
26 | | EventEmitter eventEmitter,
27 | | address account,
28 | | address market,
29 | | address collateralToken,
30 | | bool isLong
31 | * | ) internal returns (bytes32) {
32 | * | bytes32 positionKey = Position.getPositionKey(account, market, collateralToken, isLong);
33 | * | Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);
34 | |
35 | * | Order.Addresses memory addresses = Order.Addresses(
36 | * | account, // account
37 | * | account, // receiver
38 | * | account, // cancellationReceiver
39 | * | CallbackUtils.getSavedCallbackContract(dataStore, account, market), // callbackContract
40 | * | address(0), // uiFeeReceiver
41 | * | market, // market
42 | * | position.collateralToken(), // initialCollateralToken
43 | * | new address[](0) // swapPath
44 | | );
45 | |
46 | | // no slippage is set for this order, in case of a liquidation the amount
47 | | // of collateral being swapped should not be too large
48 | | // in case of large price impact, the user could be refunded
49 | | // through a protocol fund if required, this amount could later be claimed
50 | | // from the price impact pool, this claiming process should be added if
51 | | // required
52 | | //
53 | | // setting a maximum price impact that will work for majority of cases
54 | | // may also be challenging since the price impact would vary based on the
55 | | // amount of collateral being swapped
56 | | //
57 | | // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken
58 | | // because fees are calculated with reference to the collateral token
59 | | // fees are deducted from the output amount if the output token is the same as the
60 | | // collateral token
61 | | // swapping the pnl token to the collateral token helps to ensure fees can be paid
62 | | // using the realized profit
63 | * | Order.Numbers memory numbers = Order.Numbers(
64 | * | Order.OrderType.Liquidation, // orderType
65 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType
66 | * | position.sizeInUsd(), // sizeDeltaUsd
67 | * | 0, // initialCollateralDeltaAmount
68 | * | 0, // triggerPrice
69 | * | position.isLong() ? 0 : type(uint256).max, // acceptablePrice
70 | * | 0, // executionFee
71 | * | dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit
72 | * | 0, // minOutputAmount
73 | * | Chain.currentBlockNumber(), // updatedAtBlock
74 | * | Chain.currentTimestamp() // updatedAtTime
75 | | );
76 | |
77 | * | Order.Flags memory flags = Order.Flags(
78 | * | position.isLong(), // isLong
79 | * | true, // shouldUnwrapNativeToken
80 | * | false, // isFrozen
81 | * | false // autoCancel
82 | | );
83 | |
84 | * | Order.Props memory order = Order.Props(
85 | * | addresses,
86 | * | numbers,
87 | * | flags
88 | | );
89 | |
90 | * | bytes32 key = NonceUtils.getNextKey(dataStore);
91 | * | OrderStoreUtils.set(dataStore, key, order);
92 | |
93 | * | OrderEventUtils.emitOrderCreated(eventEmitter, key, order);
94 | |
95 | * | return key;
96 | | }
97 | | }
98 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/Market.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title Market
6 | | // @dev Struct for markets
7 | | //
8 | | // Markets support both spot and perp trading, they are created by specifying a
9 | | // long collateral token, short collateral token and index token.
10 | | //
11 | | // Examples:
12 | | //
13 | | // - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH
14 | | // - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC
15 | | // - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL
16 | | //
17 | | // Liquidity providers can deposit either the long or short collateral token or
18 | | // both to mint liquidity tokens.
19 | | //
20 | | // The long collateral token is used to back long positions, while the short
21 | | // collateral token is used to back short positions.
22 | | //
23 | | // Liquidity providers take on the profits and losses of traders for the market
24 | | // that they provide liquidity for.
25 | | //
26 | | // Having separate markets allows for risk isolation, liquidity providers are
27 | | // only exposed to the markets that they deposit into, this potentially allow
28 | | // for permissionless listings.
29 | | //
30 | | // Traders can use either the long or short token as collateral for the market.
31 | * | library Market {
32 | | // @param marketToken address of the market token for the market
33 | | // @param indexToken address of the index token for the market
34 | | // @param longToken address of the long token for the market
35 | | // @param shortToken address of the short token for the market
36 | | // @param data for any additional data
37 | | struct Props {
38 | | address marketToken;
39 | | address indexToken;
40 | | address longToken;
41 | | address shortToken;
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./MarketPoolValueInfo.sol";
10 | |
11 | * | library MarketEventUtils {
12 | | using EventUtils for EventUtils.AddressItems;
13 | | using EventUtils for EventUtils.UintItems;
14 | | using EventUtils for EventUtils.IntItems;
15 | | using EventUtils for EventUtils.BoolItems;
16 | | using EventUtils for EventUtils.Bytes32Items;
17 | | using EventUtils for EventUtils.BytesItems;
18 | | using EventUtils for EventUtils.StringItems;
19 | |
20 | | // this event is emitted before a deposit or withdrawal
21 | | // it provides information of the pool state so that the amount
22 | | // of market tokens minted or amount withdrawn from the pool can be checked
23 | * | function emitMarketPoolValueInfo(
24 | | EventEmitter eventEmitter,
25 | | bytes32 tradeKey,
26 | | address market,
27 | | MarketPoolValueInfo.Props memory props,
28 | | uint256 marketTokensSupply
29 | * | ) internal {
30 | * | EventUtils.EventLogData memory eventData;
31 | |
32 | * | eventData.bytes32Items.initItems(1);
33 | * | eventData.bytes32Items.setItem(0, "tradeKey", tradeKey);
34 | |
35 | * | eventData.addressItems.initItems(1);
36 | * | eventData.addressItems.setItem(0, "market", market);
37 | |
38 | * | eventData.intItems.initItems(4);
39 | * | eventData.intItems.setItem(0, "poolValue", props.poolValue);
40 | * | eventData.intItems.setItem(1, "longPnl", props.longPnl);
41 | * | eventData.intItems.setItem(2, "shortPnl", props.shortPnl);
42 | * | eventData.intItems.setItem(3, "netPnl", props.netPnl);
43 | |
44 | * | eventData.uintItems.initItems(8);
45 | * | eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount);
46 | * | eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount);
47 | * | eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd);
48 | * | eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd);
49 | * | eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees);
50 | * | eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor);
51 | * | eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount);
52 | * | eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply);
53 | |
54 | * | eventEmitter.emitEventLog1(
55 | | "MarketPoolValueInfo",
56 | * | Cast.toBytes32(market),
57 | * | eventData
58 | | );
59 | | }
60 | |
61 | | // this event is emitted after a deposit or withdrawal
62 | | // it provides information of the updated pool state
63 | | // note that the pool state can change even without a deposit / withdrawal
64 | | // e.g. borrowing fees can increase the pool's value with time, trader pnl
65 | | // will change as index prices change
66 | * | function emitMarketPoolValueUpdated(
67 | | EventEmitter eventEmitter,
68 | | bytes32 actionType,
69 | | bytes32 tradeKey,
70 | | address market,
71 | | MarketPoolValueInfo.Props memory props,
72 | | uint256 marketTokensSupply
73 | * | ) internal {
74 | * | EventUtils.EventLogData memory eventData;
75 | |
76 | * | eventData.bytes32Items.initItems(2);
77 | * | eventData.bytes32Items.setItem(0, "actionType", actionType);
78 | * | eventData.bytes32Items.setItem(1, "tradeKey", tradeKey);
79 | |
80 | * | eventData.addressItems.initItems(1);
81 | * | eventData.addressItems.setItem(0, "market", market);
82 | |
83 | * | eventData.intItems.initItems(4);
84 | * | eventData.intItems.setItem(0, "poolValue", props.poolValue);
85 | * | eventData.intItems.setItem(1, "longPnl", props.longPnl);
86 | * | eventData.intItems.setItem(2, "shortPnl", props.shortPnl);
87 | * | eventData.intItems.setItem(3, "netPnl", props.netPnl);
88 | |
89 | * | eventData.uintItems.initItems(8);
90 | * | eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount);
91 | * | eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount);
92 | * | eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd);
93 | * | eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd);
94 | * | eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees);
95 | * | eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor);
96 | * | eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount);
97 | * | eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply);
98 | |
99 | * | eventEmitter.emitEventLog1(
100 | | "MarketPoolValueUpdated",
101 | * | Cast.toBytes32(market),
102 | * | eventData
103 | | );
104 | | }
105 | |
106 | * | function emitPoolAmountUpdated(
107 | | EventEmitter eventEmitter,
108 | | address market,
109 | | address token,
110 | | int256 delta,
111 | | uint256 nextValue
112 | * | ) internal {
113 | * | EventUtils.EventLogData memory eventData;
114 | |
115 | * | eventData.addressItems.initItems(2);
116 | * | eventData.addressItems.setItem(0, "market", market);
117 | * | eventData.addressItems.setItem(1, "token", token);
118 | |
119 | * | eventData.intItems.initItems(1);
120 | * | eventData.intItems.setItem(0, "delta", delta);
121 | |
122 | * | eventData.uintItems.initItems(1);
123 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
124 | |
125 | * | eventEmitter.emitEventLog1(
126 | | "PoolAmountUpdated",
127 | * | Cast.toBytes32(market),
128 | * | eventData
129 | | );
130 | | }
131 | |
132 | * | function emitSwapImpactPoolAmountUpdated(
133 | | EventEmitter eventEmitter,
134 | | address market,
135 | | address token,
136 | | int256 delta,
137 | | uint256 nextValue
138 | * | ) internal {
139 | * | EventUtils.EventLogData memory eventData;
140 | |
141 | * | eventData.addressItems.initItems(2);
142 | * | eventData.addressItems.setItem(0, "market", market);
143 | * | eventData.addressItems.setItem(1, "token", token);
144 | |
145 | * | eventData.intItems.initItems(1);
146 | * | eventData.intItems.setItem(0, "delta", delta);
147 | |
148 | * | eventData.uintItems.initItems(1);
149 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
150 | |
151 | * | eventEmitter.emitEventLog1(
152 | | "SwapImpactPoolAmountUpdated",
153 | * | Cast.toBytes32(market),
154 | * | eventData
155 | | );
156 | | }
157 | |
158 | | function emitPositionImpactPoolDistributed(
159 | | EventEmitter eventEmitter,
160 | | address market,
161 | | uint256 distributionAmount,
162 | | uint256 nextPositionImpactPoolAmount
163 | | ) internal {
164 | | EventUtils.EventLogData memory eventData;
165 | |
166 | | eventData.addressItems.initItems(1);
167 | | eventData.addressItems.setItem(0, "market", market);
168 | |
169 | | eventData.uintItems.initItems(2);
170 | | eventData.uintItems.setItem(0, "distributionAmount", distributionAmount);
171 | | eventData.uintItems.setItem(1, "nextPositionImpactPoolAmount", nextPositionImpactPoolAmount);
172 | |
173 | | eventEmitter.emitEventLog1(
174 | | "PositionImpactPoolDistributed",
175 | | Cast.toBytes32(market),
176 | | eventData
177 | | );
178 | | }
179 | |
180 | * | function emitPositionImpactPoolAmountUpdated(
181 | | EventEmitter eventEmitter,
182 | | address market,
183 | | int256 delta,
184 | | uint256 nextValue
185 | * | ) internal {
186 | * | EventUtils.EventLogData memory eventData;
187 | |
188 | * | eventData.addressItems.initItems(1);
189 | * | eventData.addressItems.setItem(0, "market", market);
190 | |
191 | * | eventData.intItems.initItems(1);
192 | * | eventData.intItems.setItem(0, "delta", delta);
193 | |
194 | * | eventData.uintItems.initItems(1);
195 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
196 | |
197 | * | eventEmitter.emitEventLog1(
198 | | "PositionImpactPoolAmountUpdated",
199 | * | Cast.toBytes32(market),
200 | * | eventData
201 | | );
202 | | }
203 | |
204 | * | function emitOpenInterestUpdated(
205 | | EventEmitter eventEmitter,
206 | | address market,
207 | | address collateralToken,
208 | | bool isLong,
209 | | int256 delta,
210 | | uint256 nextValue
211 | * | ) internal {
212 | * | EventUtils.EventLogData memory eventData;
213 | |
214 | * | eventData.addressItems.initItems(2);
215 | * | eventData.addressItems.setItem(0, "market", market);
216 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
217 | |
218 | * | eventData.boolItems.initItems(1);
219 | * | eventData.boolItems.setItem(0, "isLong", isLong);
220 | |
221 | * | eventData.intItems.initItems(1);
222 | * | eventData.intItems.setItem(0, "delta", delta);
223 | |
224 | * | eventData.uintItems.initItems(1);
225 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
226 | |
227 | * | eventEmitter.emitEventLog1(
228 | | "OpenInterestUpdated",
229 | * | Cast.toBytes32(market),
230 | * | eventData
231 | | );
232 | | }
233 | |
234 | | function emitVirtualSwapInventoryUpdated(
235 | | EventEmitter eventEmitter,
236 | | address market,
237 | | bool isLongToken,
238 | | bytes32 virtualMarketId,
239 | | int256 delta,
240 | | uint256 nextValue
241 | | ) internal {
242 | | EventUtils.EventLogData memory eventData;
243 | |
244 | | eventData.addressItems.initItems(1);
245 | | eventData.addressItems.setItem(0, "market", market);
246 | |
247 | | eventData.boolItems.initItems(1);
248 | | eventData.boolItems.setItem(0, "isLongToken", isLongToken);
249 | |
250 | | eventData.bytes32Items.initItems(1);
251 | | eventData.bytes32Items.setItem(0, "virtualMarketId", virtualMarketId);
252 | |
253 | | eventData.intItems.initItems(1);
254 | | eventData.intItems.setItem(0, "delta", delta);
255 | |
256 | | eventData.uintItems.initItems(1);
257 | | eventData.uintItems.setItem(0, "nextValue", nextValue);
258 | |
259 | | eventEmitter.emitEventLog2(
260 | | "VirtualSwapInventoryUpdated",
261 | | Cast.toBytes32(market),
262 | | virtualMarketId,
263 | | eventData
264 | | );
265 | | }
266 | |
267 | | function emitVirtualPositionInventoryUpdated(
268 | | EventEmitter eventEmitter,
269 | | address token,
270 | | bytes32 virtualTokenId,
271 | | int256 delta,
272 | | int256 nextValue
273 | | ) internal {
274 | | EventUtils.EventLogData memory eventData;
275 | |
276 | | eventData.addressItems.initItems(1);
277 | | eventData.addressItems.setItem(0, "token", token);
278 | |
279 | | eventData.bytes32Items.initItems(1);
280 | | eventData.bytes32Items.setItem(0, "virtualTokenId", virtualTokenId);
281 | |
282 | | eventData.intItems.initItems(2);
283 | | eventData.intItems.setItem(0, "delta", delta);
284 | | eventData.intItems.setItem(1, "nextValue", nextValue);
285 | |
286 | | eventEmitter.emitEventLog2(
287 | | "VirtualPositionInventoryUpdated",
288 | | Cast.toBytes32(token),
289 | | virtualTokenId,
290 | | eventData
291 | | );
292 | | }
293 | |
294 | * | function emitOpenInterestInTokensUpdated(
295 | | EventEmitter eventEmitter,
296 | | address market,
297 | | address collateralToken,
298 | | bool isLong,
299 | | int256 delta,
300 | | uint256 nextValue
301 | * | ) internal {
302 | * | EventUtils.EventLogData memory eventData;
303 | |
304 | * | eventData.addressItems.initItems(2);
305 | * | eventData.addressItems.setItem(0, "market", market);
306 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
307 | |
308 | * | eventData.boolItems.initItems(1);
309 | * | eventData.boolItems.setItem(0, "isLong", isLong);
310 | |
311 | * | eventData.intItems.initItems(1);
312 | * | eventData.intItems.setItem(0, "delta", delta);
313 | |
314 | * | eventData.uintItems.initItems(1);
315 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
316 | |
317 | * | eventEmitter.emitEventLog1(
318 | | "OpenInterestInTokensUpdated",
319 | * | Cast.toBytes32(market),
320 | * | eventData
321 | | );
322 | | }
323 | |
324 | * | function emitCollateralSumUpdated(
325 | | EventEmitter eventEmitter,
326 | | address market,
327 | | address collateralToken,
328 | | bool isLong,
329 | | int256 delta,
330 | | uint256 nextValue
331 | * | ) internal {
332 | * | EventUtils.EventLogData memory eventData;
333 | |
334 | * | eventData.addressItems.initItems(2);
335 | * | eventData.addressItems.setItem(0, "market", market);
336 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
337 | |
338 | * | eventData.boolItems.initItems(1);
339 | * | eventData.boolItems.setItem(0, "isLong", isLong);
340 | |
341 | * | eventData.intItems.initItems(1);
342 | * | eventData.intItems.setItem(0, "delta", delta);
343 | |
344 | * | eventData.uintItems.initItems(1);
345 | * | eventData.uintItems.setItem(0, "nextValue", nextValue);
346 | |
347 | * | eventEmitter.emitEventLog1(
348 | | "CollateralSumUpdated",
349 | * | Cast.toBytes32(market),
350 | * | eventData
351 | | );
352 | | }
353 | |
354 | * | function emitBorrowingFactorUpdated(
355 | | EventEmitter eventEmitter,
356 | | address market,
357 | | bool isLong,
358 | | uint256 delta,
359 | | uint256 nextValue
360 | * | ) internal {
361 | * | EventUtils.EventLogData memory eventData;
362 | |
363 | * | eventData.addressItems.initItems(1);
364 | * | eventData.addressItems.setItem(0, "market", market);
365 | |
366 | * | eventData.boolItems.initItems(1);
367 | * | eventData.boolItems.setItem(0, "isLong", isLong);
368 | |
369 | * | eventData.uintItems.initItems(2);
370 | * | eventData.uintItems.setItem(0, "delta", delta);
371 | * | eventData.uintItems.setItem(1, "nextValue", nextValue);
372 | |
373 | * | eventEmitter.emitEventLog1(
374 | | "CumulativeBorrowingFactorUpdated",
375 | * | Cast.toBytes32(market),
376 | * | eventData
377 | | );
378 | | }
379 | |
380 | * | function emitFundingFeeAmountPerSizeUpdated(
381 | | EventEmitter eventEmitter,
382 | | address market,
383 | | address collateralToken,
384 | | bool isLong,
385 | | uint256 delta,
386 | | uint256 value
387 | * | ) internal {
388 | * | EventUtils.EventLogData memory eventData;
389 | |
390 | * | eventData.addressItems.initItems(2);
391 | * | eventData.addressItems.setItem(0, "market", market);
392 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
393 | |
394 | * | eventData.boolItems.initItems(1);
395 | * | eventData.boolItems.setItem(0, "isLong", isLong);
396 | |
397 | * | eventData.uintItems.initItems(2);
398 | * | eventData.uintItems.setItem(0, "delta", delta);
399 | * | eventData.uintItems.setItem(1, "value", value);
400 | |
401 | * | eventEmitter.emitEventLog1(
402 | | "FundingFeeAmountPerSizeUpdated",
403 | * | Cast.toBytes32(market),
404 | * | eventData
405 | | );
406 | | }
407 | |
408 | * | function emitClaimableFundingAmountPerSizeUpdated(
409 | | EventEmitter eventEmitter,
410 | | address market,
411 | | address collateralToken,
412 | | bool isLong,
413 | | uint256 delta,
414 | | uint256 value
415 | * | ) internal {
416 | * | EventUtils.EventLogData memory eventData;
417 | |
418 | * | eventData.addressItems.initItems(2);
419 | * | eventData.addressItems.setItem(0, "market", market);
420 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
421 | |
422 | * | eventData.boolItems.initItems(1);
423 | * | eventData.boolItems.setItem(0, "isLong", isLong);
424 | |
425 | * | eventData.uintItems.initItems(2);
426 | * | eventData.uintItems.setItem(0, "delta", delta);
427 | * | eventData.uintItems.setItem(1, "value", value);
428 | |
429 | * | eventEmitter.emitEventLog1(
430 | | "ClaimableFundingAmountPerSizeUpdated",
431 | * | Cast.toBytes32(market),
432 | * | eventData
433 | | );
434 | | }
435 | |
436 | * | function emitClaimableFundingUpdated(
437 | | EventEmitter eventEmitter,
438 | | address market,
439 | | address token,
440 | | address account,
441 | | uint256 delta,
442 | | uint256 nextValue,
443 | | uint256 nextPoolValue
444 | * | ) internal {
445 | * | EventUtils.EventLogData memory eventData;
446 | |
447 | * | eventData.addressItems.initItems(3);
448 | * | eventData.addressItems.setItem(0, "market", market);
449 | * | eventData.addressItems.setItem(1, "token", token);
450 | * | eventData.addressItems.setItem(2, "account", account);
451 | |
452 | * | eventData.uintItems.initItems(3);
453 | * | eventData.uintItems.setItem(0, "delta", delta);
454 | * | eventData.uintItems.setItem(1, "nextValue", nextValue);
455 | * | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
456 | |
457 | * | eventEmitter.emitEventLog1(
458 | | "ClaimableFundingUpdated",
459 | * | Cast.toBytes32(account),
460 | * | eventData
461 | | );
462 | | }
463 | |
464 | * | function emitFundingFeesClaimed(
465 | | EventEmitter eventEmitter,
466 | | address market,
467 | | address token,
468 | | address account,
469 | | address receiver,
470 | | uint256 amount,
471 | | uint256 nextPoolValue
472 | * | ) internal {
473 | * | EventUtils.EventLogData memory eventData;
474 | |
475 | * | eventData.addressItems.initItems(4);
476 | * | eventData.addressItems.setItem(0, "market", market);
477 | * | eventData.addressItems.setItem(1, "token", token);
478 | * | eventData.addressItems.setItem(2, "account", account);
479 | * | eventData.addressItems.setItem(3, "receiver", receiver);
480 | |
481 | * | eventData.uintItems.initItems(2);
482 | * | eventData.uintItems.setItem(0, "amount", amount);
483 | * | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
484 | |
485 | * | eventEmitter.emitEventLog1(
486 | | "FundingFeesClaimed",
487 | * | Cast.toBytes32(account),
488 | * | eventData
489 | | );
490 | | }
491 | |
492 | | function emitClaimableFundingUpdated(
493 | | EventEmitter eventEmitter,
494 | | address market,
495 | | address token,
496 | | uint256 timeKey,
497 | | address account,
498 | | uint256 delta,
499 | | uint256 nextValue
500 | | ) internal {
501 | | EventUtils.EventLogData memory eventData;
502 | |
503 | | eventData.addressItems.initItems(3);
504 | | eventData.addressItems.setItem(0, "market", market);
505 | | eventData.addressItems.setItem(1, "token", token);
506 | | eventData.addressItems.setItem(2, "account", account);
507 | |
508 | | eventData.uintItems.initItems(3);
509 | | eventData.uintItems.setItem(0, "timeKey", timeKey);
510 | | eventData.uintItems.setItem(1, "delta", delta);
511 | | eventData.uintItems.setItem(2, "nextValue", nextValue);
512 | |
513 | | eventEmitter.emitEventLog1(
514 | | "ClaimableFundingUpdated",
515 | | Cast.toBytes32(account),
516 | | eventData
517 | | );
518 | | }
519 | |
520 | | function emitClaimableCollateralUpdated(
521 | | EventEmitter eventEmitter,
522 | | address market,
523 | | address token,
524 | | uint256 timeKey,
525 | | address account,
526 | | uint256 delta,
527 | | uint256 nextValue,
528 | | uint256 nextPoolValue
529 | | ) internal {
530 | | EventUtils.EventLogData memory eventData;
531 | |
532 | | eventData.addressItems.initItems(3);
533 | | eventData.addressItems.setItem(0, "market", market);
534 | | eventData.addressItems.setItem(1, "token", token);
535 | | eventData.addressItems.setItem(2, "account", account);
536 | |
537 | | eventData.uintItems.initItems(4);
538 | | eventData.uintItems.setItem(0, "timeKey", timeKey);
539 | | eventData.uintItems.setItem(1, "delta", delta);
540 | | eventData.uintItems.setItem(2, "nextValue", nextValue);
541 | | eventData.uintItems.setItem(3, "nextPoolValue", nextPoolValue);
542 | |
543 | | eventEmitter.emitEventLog1(
544 | | "ClaimableCollateralUpdated",
545 | | Cast.toBytes32(account),
546 | | eventData
547 | | );
548 | | }
549 | |
550 | | function emitCollateralClaimed(
551 | | EventEmitter eventEmitter,
552 | | address market,
553 | | address token,
554 | | uint256 timeKey,
555 | | address account,
556 | | address receiver,
557 | | uint256 amount,
558 | | uint256 nextPoolValue
559 | | ) internal {
560 | | EventUtils.EventLogData memory eventData;
561 | |
562 | | eventData.addressItems.initItems(4);
563 | | eventData.addressItems.setItem(0, "market", market);
564 | | eventData.addressItems.setItem(1, "token", token);
565 | | eventData.addressItems.setItem(2, "account", account);
566 | | eventData.addressItems.setItem(3, "receiver", receiver);
567 | |
568 | | eventData.uintItems.initItems(3);
569 | | eventData.uintItems.setItem(0, "timeKey", timeKey);
570 | | eventData.uintItems.setItem(1, "amount", amount);
571 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
572 | |
573 | | eventEmitter.emitEventLog1(
574 | | "CollateralClaimed",
575 | | Cast.toBytes32(account),
576 | | eventData
577 | | );
578 | | }
579 | |
580 | | function emitUiFeeFactorUpdated(
581 | | EventEmitter eventEmitter,
582 | | address account,
583 | | uint256 uiFeeFactor
584 | | ) internal {
585 | |
586 | | EventUtils.EventLogData memory eventData;
587 | |
588 | | eventData.addressItems.initItems(1);
589 | | eventData.addressItems.setItem(0, "account", account);
590 | |
591 | | eventData.uintItems.initItems(1);
592 | | eventData.uintItems.setItem(0, "uiFeeFactor", uiFeeFactor);
593 | |
594 | | eventEmitter.emitEventLog1(
595 | | "UiFeeFactorUpdated",
596 | | Cast.toBytes32(account),
597 | | eventData
598 | | );
599 | | }
600 | | }
601 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketFactory.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./MarketToken.sol";
6 | | import "./Market.sol";
7 | | import "./MarketStoreUtils.sol";
8 | | import "../event/EventEmitter.sol";
9 | | import "../utils/Cast.sol";
10 | |
11 | | // @title MarketFactory
12 | | // @dev Contract to create markets
13 | * | contract MarketFactory is RoleModule {
14 | | using Market for Market.Props;
15 | |
16 | | using EventUtils for EventUtils.AddressItems;
17 | | using EventUtils for EventUtils.UintItems;
18 | | using EventUtils for EventUtils.IntItems;
19 | | using EventUtils for EventUtils.BoolItems;
20 | | using EventUtils for EventUtils.Bytes32Items;
21 | | using EventUtils for EventUtils.BytesItems;
22 | | using EventUtils for EventUtils.StringItems;
23 | |
24 | | DataStore public immutable dataStore;
25 | | EventEmitter public immutable eventEmitter;
26 | |
27 | | constructor(
28 | | RoleStore _roleStore,
29 | | DataStore _dataStore,
30 | | EventEmitter _eventEmitter
31 | | ) RoleModule(_roleStore) {
32 | | dataStore = _dataStore;
33 | | eventEmitter = _eventEmitter;
34 | | }
35 | |
36 | | // @dev creates a market
37 | | // @param indexToken address of the index token for the market
38 | | // @param longToken address of the long token for the market
39 | | // @param shortToken address of the short token for the market
40 | | // @param marketType the type of the market
41 | | function createMarket(
42 | | address indexToken,
43 | | address longToken,
44 | | address shortToken,
45 | | bytes32 marketType
46 | | ) external onlyMarketKeeper returns (Market.Props memory) {
47 | | bytes32 salt = keccak256(abi.encode(
48 | | "GMX_MARKET",
49 | | indexToken,
50 | | longToken,
51 | | shortToken,
52 | | marketType
53 | | ));
54 | |
55 | | address existingMarketAddress = dataStore.getAddress(MarketStoreUtils.getMarketSaltHash(salt));
56 | | if (existingMarketAddress != address(0)) {
57 | | revert Errors.MarketAlreadyExists(salt, existingMarketAddress);
58 | | }
59 | |
60 | | MarketToken marketToken = new MarketToken{salt: salt}(roleStore, dataStore);
61 | |
62 | | // the marketType is not stored with the market, it is mainly used to ensure
63 | | // markets with the same indexToken, longToken and shortToken can be created if needed
64 | | Market.Props memory market = Market.Props(
65 | | address(marketToken),
66 | | indexToken,
67 | | longToken,
68 | | shortToken
69 | | );
70 | |
71 | | MarketStoreUtils.set(dataStore, address(marketToken), salt, market);
72 | |
73 | | emitMarketCreated(address(marketToken), salt, indexToken, longToken, shortToken);
74 | |
75 | | return market;
76 | | }
77 | |
78 | | function emitMarketCreated(
79 | | address marketToken,
80 | | bytes32 salt,
81 | | address indexToken,
82 | | address longToken,
83 | | address shortToken
84 | | ) internal {
85 | | EventUtils.EventLogData memory eventData;
86 | |
87 | | eventData.addressItems.initItems(4);
88 | | eventData.addressItems.setItem(0, "marketToken", marketToken);
89 | | eventData.addressItems.setItem(1, "indexToken", indexToken);
90 | | eventData.addressItems.setItem(2, "longToken", longToken);
91 | | eventData.addressItems.setItem(3, "shortToken", shortToken);
92 | |
93 | | eventData.bytes32Items.initItems(1);
94 | | eventData.bytes32Items.setItem(0, "salt", salt);
95 | |
96 | | eventEmitter.emitEventLog1(
97 | | "MarketCreated",
98 | | Cast.toBytes32(marketToken),
99 | | eventData
100 | | );
101 | | }
102 | | }
103 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketPoolValueInfo.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title MarketPoolInfo
6 | * | library MarketPoolValueInfo {
7 | | // @dev struct to avoid stack too deep errors for the getPoolValue call
8 | | // @param value the pool value
9 | | // @param longTokenAmount the amount of long token in the pool
10 | | // @param shortTokenAmount the amount of short token in the pool
11 | | // @param longTokenUsd the USD value of the long tokens in the pool
12 | | // @param shortTokenUsd the USD value of the short tokens in the pool
13 | | // @param totalBorrowingFees the total pending borrowing fees for the market
14 | | // @param borrowingFeePoolFactor the pool factor for borrowing fees
15 | | // @param impactPoolAmount the amount of tokens in the impact pool
16 | | // @param longPnl the pending pnl of long positions
17 | | // @param shortPnl the pending pnl of short positions
18 | | // @param netPnl the net pnl of long and short positions
19 | | struct Props {
20 | | int256 poolValue;
21 | | int256 longPnl;
22 | | int256 shortPnl;
23 | | int256 netPnl;
24 | |
25 | | uint256 longTokenAmount;
26 | | uint256 shortTokenAmount;
27 | | uint256 longTokenUsd;
28 | | uint256 shortTokenUsd;
29 | |
30 | | uint256 totalBorrowingFees;
31 | | uint256 borrowingFeePoolFactor;
32 | |
33 | | uint256 impactPoolAmount;
34 | | }
35 | | }
36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Market.sol";
9 | |
10 | | /**
11 | | * @title MarketStoreUtils
12 | | * @dev Library for market storage functions
13 | | */
14 | * | library MarketStoreUtils {
15 | | using Market for Market.Props;
16 | |
17 | | bytes32 internal constant MARKET_SALT = keccak256(abi.encode("MARKET_SALT"));
18 | | bytes32 internal constant MARKET_KEY = keccak256(abi.encode("MARKET_KEY"));
19 | * | bytes32 internal constant MARKET_TOKEN = keccak256(abi.encode("MARKET_TOKEN"));
20 | * | bytes32 internal constant INDEX_TOKEN = keccak256(abi.encode("INDEX_TOKEN"));
21 | * | bytes32 internal constant LONG_TOKEN = keccak256(abi.encode("LONG_TOKEN"));
22 | * | bytes32 internal constant SHORT_TOKEN = keccak256(abi.encode("SHORT_TOKEN"));
23 | |
24 | * | function get(DataStore dataStore, address key) internal view returns (Market.Props memory) {
25 | * | Market.Props memory market;
26 | * | if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {
27 | * | return market;
28 | | }
29 | |
30 | * | market.marketToken = dataStore.getAddress(
31 | * | keccak256(abi.encode(key, MARKET_TOKEN))
32 | | );
33 | |
34 | * | market.indexToken = dataStore.getAddress(
35 | * | keccak256(abi.encode(key, INDEX_TOKEN))
36 | | );
37 | |
38 | * | market.longToken = dataStore.getAddress(
39 | * | keccak256(abi.encode(key, LONG_TOKEN))
40 | | );
41 | |
42 | * | market.shortToken = dataStore.getAddress(
43 | * | keccak256(abi.encode(key, SHORT_TOKEN))
44 | | );
45 | |
46 | * | return market;
47 | | }
48 | |
49 | | function getBySalt(DataStore dataStore, bytes32 salt) internal view returns (Market.Props memory) {
50 | | address key = dataStore.getAddress(getMarketSaltHash(salt));
51 | | return get(dataStore, key);
52 | | }
53 | |
54 | | function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) internal {
55 | | dataStore.addAddress(
56 | | Keys.MARKET_LIST,
57 | | key
58 | | );
59 | |
60 | | // the salt is based on the market props while the key gives the market's address
61 | | // use the salt to store a reference to the key to allow the key to be retrieved
62 | | // using just the salt value
63 | | dataStore.setAddress(
64 | | getMarketSaltHash(salt),
65 | | key
66 | | );
67 | |
68 | | dataStore.setAddress(
69 | | keccak256(abi.encode(key, MARKET_TOKEN)),
70 | | market.marketToken
71 | | );
72 | |
73 | | dataStore.setAddress(
74 | | keccak256(abi.encode(key, INDEX_TOKEN)),
75 | | market.indexToken
76 | | );
77 | |
78 | | dataStore.setAddress(
79 | | keccak256(abi.encode(key, LONG_TOKEN)),
80 | | market.longToken
81 | | );
82 | |
83 | | dataStore.setAddress(
84 | | keccak256(abi.encode(key, SHORT_TOKEN)),
85 | | market.shortToken
86 | | );
87 | | }
88 | |
89 | | function remove(DataStore dataStore, address key) internal {
90 | | if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {
91 | | revert Errors.MarketNotFound(key);
92 | | }
93 | |
94 | | dataStore.removeAddress(
95 | | Keys.MARKET_LIST,
96 | | key
97 | | );
98 | |
99 | | dataStore.removeAddress(
100 | | keccak256(abi.encode(key, MARKET_TOKEN))
101 | | );
102 | |
103 | | dataStore.removeAddress(
104 | | keccak256(abi.encode(key, INDEX_TOKEN))
105 | | );
106 | |
107 | | dataStore.removeAddress(
108 | | keccak256(abi.encode(key, LONG_TOKEN))
109 | | );
110 | |
111 | | dataStore.removeAddress(
112 | | keccak256(abi.encode(key, SHORT_TOKEN))
113 | | );
114 | | }
115 | |
116 | | function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {
117 | | return keccak256(abi.encode(MARKET_SALT, salt));
118 | | }
119 | |
120 | | function getMarketCount(DataStore dataStore) internal view returns (uint256) {
121 | | return dataStore.getAddressCount(Keys.MARKET_LIST);
122 | | }
123 | |
124 | | function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {
125 | | return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);
126 | | }
127 | | }
128 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketToken.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6 | | import "../bank/Bank.sol";
7 | |
8 | | // @title MarketToken
9 | | // @dev The market token for a market, stores funds for the market and keeps track
10 | | // of the liquidity owners
11 | * | contract MarketToken is ERC20, Bank {
12 | | constructor(RoleStore _roleStore, DataStore _dataStore) ERC20("GMX Market", "GM") Bank(_roleStore, _dataStore) {
13 | | }
14 | |
15 | | // @dev mint market tokens to an account
16 | | // @param account the account to mint to
17 | | // @param amount the amount of tokens to mint
18 | * | function mint(address account, uint256 amount) external onlyController {
19 | * | _mint(account, amount);
20 | | }
21 | |
22 | | // @dev burn market tokens from an account
23 | | // @param account the account to burn tokens for
24 | | // @param amount the amount of tokens to burn
25 | * | function burn(address account, uint256 amount) external onlyController {
26 | * | _burn(account, amount);
27 | | }
28 | | }
29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../event/EventEmitter.sol";
9 | | import "../bank/StrictBank.sol";
10 | |
11 | | import "./Market.sol";
12 | | import "./MarketPoolValueInfo.sol";
13 | | import "./MarketToken.sol";
14 | | import "./MarketEventUtils.sol";
15 | | import "./MarketStoreUtils.sol";
16 | |
17 | | import "../position/Position.sol";
18 | | import "../order/Order.sol";
19 | |
20 | | import "../oracle/Oracle.sol";
21 | | import "../price/Price.sol";
22 | |
23 | | import "../utils/Calc.sol";
24 | | import "../utils/Precision.sol";
25 | | import {console} from "lib/forge-std/src/Test.sol";
26 | |
27 | | // @title MarketUtils
28 | | // @dev Library for market functions
29 | * | library MarketUtils {
30 | | using SignedMath for int256;
31 | | using SafeCast for int256;
32 | | using SafeCast for uint256;
33 | |
34 | | using Market for Market.Props;
35 | | using Position for Position.Props;
36 | | using Order for Order.Props;
37 | | using Price for Price.Props;
38 | |
39 | | enum FundingRateChangeType {
40 | | NoChange,
41 | | Increase,
42 | | Decrease
43 | | }
44 | |
45 | | // @dev struct to store the prices of tokens of a market
46 | | // @param indexTokenPrice price of the market's index token
47 | | // @param longTokenPrice price of the market's long token
48 | | // @param shortTokenPrice price of the market's short token
49 | | struct MarketPrices {
50 | | Price.Props indexTokenPrice;
51 | | Price.Props longTokenPrice;
52 | | Price.Props shortTokenPrice;
53 | | }
54 | |
55 | | struct CollateralType {
56 | | uint256 longToken;
57 | | uint256 shortToken;
58 | | }
59 | |
60 | | struct PositionType {
61 | | CollateralType long;
62 | | CollateralType short;
63 | | }
64 | |
65 | | // @dev struct for the result of the getNextFundingAmountPerSize call
66 | | // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond
67 | | // see getNextFundingFactorPerSecond for more info
68 | | struct GetNextFundingAmountPerSizeResult {
69 | | bool longsPayShorts;
70 | | uint256 fundingFactorPerSecond;
71 | | int256 nextSavedFundingFactorPerSecond;
72 | | PositionType fundingFeeAmountPerSizeDelta;
73 | | PositionType claimableFundingAmountPerSizeDelta;
74 | | }
75 | |
76 | | struct GetNextFundingAmountPerSizeCache {
77 | | PositionType openInterest;
78 | | uint256 longOpenInterest;
79 | | uint256 shortOpenInterest;
80 | | uint256 durationInSeconds;
81 | | uint256 sizeOfLargerSide;
82 | | uint256 fundingUsd;
83 | | uint256 fundingUsdForLongCollateral;
84 | | uint256 fundingUsdForShortCollateral;
85 | | }
86 | |
87 | | struct GetNextFundingFactorPerSecondCache {
88 | | uint256 diffUsd;
89 | | uint256 totalOpenInterest;
90 | | uint256 fundingFactor;
91 | | uint256 fundingExponentFactor;
92 | | uint256 diffUsdAfterExponent;
93 | | uint256 diffUsdToOpenInterestFactor;
94 | | int256 savedFundingFactorPerSecond;
95 | | uint256 savedFundingFactorPerSecondMagnitude;
96 | | int256 nextSavedFundingFactorPerSecond;
97 | | int256 nextSavedFundingFactorPerSecondWithMinBound;
98 | | }
99 | |
100 | | struct FundingConfigCache {
101 | | uint256 thresholdForStableFunding;
102 | | uint256 thresholdForDecreaseFunding;
103 | | uint256 fundingIncreaseFactorPerSecond;
104 | | uint256 fundingDecreaseFactorPerSecond;
105 | | uint256 minFundingFactorPerSecond;
106 | | uint256 maxFundingFactorPerSecond;
107 | | }
108 | |
109 | | struct GetExpectedMinTokenBalanceCache {
110 | | uint256 poolAmount;
111 | | uint256 swapImpactPoolAmount;
112 | | uint256 claimableCollateralAmount;
113 | | uint256 claimableFeeAmount;
114 | | uint256 claimableUiFeeAmount;
115 | | uint256 affiliateRewardAmount;
116 | | }
117 | |
118 | | // @dev get the market token's price
119 | | // @param dataStore DataStore
120 | | // @param market the market to check
121 | | // @param longTokenPrice the price of the long token
122 | | // @param shortTokenPrice the price of the short token
123 | | // @param indexTokenPrice the price of the index token
124 | | // @param maximize whether to maximize or minimize the market token price
125 | | // @return returns (the market token's price, MarketPoolValueInfo.Props)
126 | | function getMarketTokenPrice(
127 | | DataStore dataStore,
128 | | Market.Props memory market,
129 | | Price.Props memory indexTokenPrice,
130 | | Price.Props memory longTokenPrice,
131 | | Price.Props memory shortTokenPrice,
132 | | bytes32 pnlFactorType,
133 | | bool maximize
134 | | ) internal view returns (int256, MarketPoolValueInfo.Props memory) {
135 | | uint256 supply = getMarketTokenSupply(
136 | | MarketToken(payable(market.marketToken))
137 | | );
138 | |
139 | | MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(
140 | | dataStore,
141 | | market,
142 | | indexTokenPrice,
143 | | longTokenPrice,
144 | | shortTokenPrice,
145 | | pnlFactorType,
146 | | maximize
147 | | );
148 | |
149 | | // if the supply is zero then treat the market token price as 1 USD
150 | | if (supply == 0) {
151 | | return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);
152 | | }
153 | |
154 | | if (poolValueInfo.poolValue == 0) {
155 | | return (0, poolValueInfo);
156 | | }
157 | |
158 | | int256 marketTokenPrice = Precision.mulDiv(
159 | | Precision.WEI_PRECISION,
160 | | poolValueInfo.poolValue,
161 | | supply
162 | | );
163 | | return (marketTokenPrice, poolValueInfo);
164 | | }
165 | |
166 | | // @dev get the total supply of the marketToken
167 | | // @param marketToken the marketToken
168 | | // @return the total supply of the marketToken
169 | * | function getMarketTokenSupply(
170 | | MarketToken marketToken
171 | * | ) internal view returns (uint256) {
172 | * | return marketToken.totalSupply();
173 | | }
174 | |
175 | | // @dev get the opposite token of the market
176 | | // if the inputToken is the longToken return the shortToken and vice versa
177 | | // @param inputToken the input token
178 | | // @param market the market values
179 | | // @return the opposite token
180 | * | function getOppositeToken(
181 | | address inputToken,
182 | | Market.Props memory market
183 | * | ) internal pure returns (address) {
184 | * | if (inputToken == market.longToken) {
185 | * | return market.shortToken;
186 | | }
187 | |
188 | * | if (inputToken == market.shortToken) {
189 | * | return market.longToken;
190 | | }
191 | |
192 | | revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);
193 | | }
194 | |
195 | * | function validateSwapMarket(
196 | | DataStore dataStore,
197 | | address marketAddress
198 | * | ) internal view {
199 | * | Market.Props memory market = MarketStoreUtils.get(
200 | * | dataStore,
201 | * | marketAddress
202 | | );
203 | * | validateSwapMarket(dataStore, market);
204 | | }
205 | |
206 | * | function validateSwapMarket(
207 | | DataStore dataStore,
208 | | Market.Props memory market
209 | | ) internal view {
210 | * | validateEnabledMarket(dataStore, market);
211 | |
212 | * | if (market.longToken == market.shortToken) {
213 | | revert Errors.InvalidSwapMarket(market.marketToken);
214 | | }
215 | | }
216 | |
217 | | // @dev get the token price from the stored MarketPrices
218 | | // @param token the token to get the price for
219 | | // @param the market values
220 | | // @param the market token prices
221 | | // @return the token price from the stored MarketPrices
222 | * | function getCachedTokenPrice(
223 | | address token,
224 | | Market.Props memory market,
225 | | MarketPrices memory prices
226 | * | ) internal pure returns (Price.Props memory) {
227 | * | if (token == market.longToken) {
228 | * | return prices.longTokenPrice;
229 | | }
230 | * | if (token == market.shortToken) {
231 | * | return prices.shortTokenPrice;
232 | | }
233 | | if (token == market.indexToken) {
234 | | return prices.indexTokenPrice;
235 | | }
236 | |
237 | | revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);
238 | | }
239 | |
240 | | // @dev return the primary prices for the market tokens
241 | | // @param oracle Oracle
242 | | // @param market the market values
243 | * | function getMarketPrices(
244 | | Oracle oracle,
245 | | Market.Props memory market
246 | * | ) internal view returns (MarketPrices memory) {
247 | * | return
248 | * | MarketPrices(
249 | * | oracle.getPrimaryPrice(market.indexToken),
250 | * | oracle.getPrimaryPrice(market.longToken),
251 | * | oracle.getPrimaryPrice(market.shortToken)
252 | | );
253 | | }
254 | |
255 | | // @dev get the usd value of either the long or short tokens in the pool
256 | | // without accounting for the pnl of open positions
257 | | // @param dataStore DataStore
258 | | // @param market the market values
259 | | // @param prices the prices of the market tokens
260 | | // @param whether to return the value for the long or short token
261 | | // @return the usd value of either the long or short tokens in the pool
262 | * | function getPoolUsdWithoutPnl(
263 | | DataStore dataStore,
264 | | Market.Props memory market,
265 | | MarketPrices memory prices,
266 | | bool isLong,
267 | | bool maximize
268 | * | ) internal view returns (uint256) {
269 | * | address token = isLong ? market.longToken : market.shortToken;
270 | | // note that if it is a single token market, the poolAmount returned will be
271 | | // the amount of tokens in the pool divided by 2
272 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token);
273 | * | uint256 tokenPrice;
274 | |
275 | * | if (maximize) {
276 | | tokenPrice = isLong
277 | | ? prices.longTokenPrice.max
278 | | : prices.shortTokenPrice.max;
279 | | } else {
280 | * | tokenPrice = isLong
281 | * | ? prices.longTokenPrice.min
282 | * | : prices.shortTokenPrice.min;
283 | | }
284 | |
285 | * | return poolAmount * tokenPrice;
286 | | }
287 | |
288 | | // @dev get the USD value of a pool
289 | | // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl
290 | | // we use the token index prices to calculate this and ignore price impact since if all positions were closed the
291 | | // net price impact should be zero
292 | | // @param dataStore DataStore
293 | | // @param market the market values
294 | | // @param longTokenPrice price of the long token
295 | | // @param shortTokenPrice price of the short token
296 | | // @param indexTokenPrice price of the index token
297 | | // @param maximize whether to maximize or minimize the pool value
298 | | // @return the value information of a pool
299 | * | function getPoolValueInfo(
300 | | DataStore dataStore,
301 | | Market.Props memory market,
302 | | Price.Props memory indexTokenPrice,
303 | | Price.Props memory longTokenPrice,
304 | | Price.Props memory shortTokenPrice,
305 | | bytes32 pnlFactorType,
306 | | bool maximize
307 | * | ) internal view returns (MarketPoolValueInfo.Props memory) {
308 | * | MarketPoolValueInfo.Props memory result;
309 | |
310 | * | result.longTokenAmount = getPoolAmount(
311 | * | dataStore,
312 | * | market,
313 | * | market.longToken
314 | | );
315 | * | result.shortTokenAmount = getPoolAmount(
316 | * | dataStore,
317 | * | market,
318 | * | market.shortToken
319 | | );
320 | |
321 | * | result.longTokenUsd =
322 | * | result.longTokenAmount *
323 | * | longTokenPrice.pickPrice(maximize);
324 | * | result.shortTokenUsd =
325 | * | result.shortTokenAmount *
326 | * | shortTokenPrice.pickPrice(maximize);
327 | |
328 | * | result.poolValue = (result.longTokenUsd + result.shortTokenUsd)
329 | | .toInt256();
330 | |
331 | * | MarketPrices memory prices = MarketPrices(
332 | * | indexTokenPrice,
333 | * | longTokenPrice,
334 | * | shortTokenPrice
335 | | );
336 | |
337 | * | result.totalBorrowingFees = getTotalPendingBorrowingFees(
338 | * | dataStore,
339 | * | market,
340 | * | prices,
341 | * | true
342 | | );
343 | |
344 | * | result.totalBorrowingFees += getTotalPendingBorrowingFees(
345 | * | dataStore,
346 | * | market,
347 | * | prices,
348 | * | false
349 | | );
350 | |
351 | * | result.borrowingFeePoolFactor =
352 | * | Precision.FLOAT_PRECISION -
353 | * | dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);
354 | * | result.poolValue += Precision
355 | | .applyFactor(
356 | * | result.totalBorrowingFees,
357 | * | result.borrowingFeePoolFactor
358 | | )
359 | | .toInt256();
360 | |
361 | | // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value
362 | | // and a smaller pnl leads to a larger pool value
363 | | //
364 | | // while positions will always be closed at the less favourable price
365 | | // using the inverse of maximize for the getPnl calls would help prevent
366 | | // gaming of market token values by increasing the spread
367 | | //
368 | | // liquidations could be triggerred by manipulating a large spread but
369 | | // that should be more difficult to execute
370 | |
371 | * | result.longPnl = getPnl(
372 | * | dataStore,
373 | * | market,
374 | * | indexTokenPrice,
375 | * | true, // isLong
376 | * | !maximize // maximize
377 | | );
378 | |
379 | * | result.longPnl = getCappedPnl(
380 | * | dataStore,
381 | * | market.marketToken,
382 | * | true,
383 | * | result.longPnl,
384 | * | result.longTokenUsd,
385 | * | pnlFactorType
386 | | );
387 | |
388 | * | result.shortPnl = getPnl(
389 | * | dataStore,
390 | * | market,
391 | * | indexTokenPrice,
392 | * | false, // isLong
393 | * | !maximize // maximize
394 | | );
395 | |
396 | * | result.shortPnl = getCappedPnl(
397 | * | dataStore,
398 | * | market.marketToken,
399 | * | false,
400 | * | result.shortPnl,
401 | * | result.shortTokenUsd,
402 | * | pnlFactorType
403 | | );
404 | |
405 | * | result.netPnl = result.longPnl + result.shortPnl;
406 | * | result.poolValue = result.poolValue - result.netPnl;
407 | |
408 | * | result.impactPoolAmount = getNextPositionImpactPoolAmount(
409 | * | dataStore,
410 | * | market.marketToken
411 | | );
412 | | // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue
413 | * | uint256 impactPoolUsd = result.impactPoolAmount *
414 | * | indexTokenPrice.pickPrice(!maximize);
415 | |
416 | * | result.poolValue -= impactPoolUsd.toInt256();
417 | |
418 | * | return result;
419 | | }
420 | |
421 | | // @dev get the net pending pnl for a market
422 | | // @param dataStore DataStore
423 | | // @param market the market to check
424 | | // @param longToken the long token of the market
425 | | // @param shortToken the short token of the market
426 | | // @param indexTokenPrice the price of the index token
427 | | // @param maximize whether to maximize or minimize the net pnl
428 | | // @return the net pending pnl for a market
429 | | function getNetPnl(
430 | | DataStore dataStore,
431 | | Market.Props memory market,
432 | | Price.Props memory indexTokenPrice,
433 | | bool maximize
434 | | ) internal view returns (int256) {
435 | | int256 longPnl = getPnl(
436 | | dataStore,
437 | | market,
438 | | indexTokenPrice,
439 | | true,
440 | | maximize
441 | | );
442 | | int256 shortPnl = getPnl(
443 | | dataStore,
444 | | market,
445 | | indexTokenPrice,
446 | | false,
447 | | maximize
448 | | );
449 | |
450 | | return longPnl + shortPnl;
451 | | }
452 | |
453 | | // @dev get the capped pending pnl for a market
454 | | // @param dataStore DataStore
455 | | // @param market the market to check
456 | | // @param isLong whether to check for the long or short side
457 | | // @param pnl the uncapped pnl of the market
458 | | // @param poolUsd the USD value of the pool
459 | | // @param pnlFactorType the pnl factor type to use
460 | * | function getCappedPnl(
461 | | DataStore dataStore,
462 | | address market,
463 | | bool isLong,
464 | | int256 pnl,
465 | | uint256 poolUsd,
466 | | bytes32 pnlFactorType
467 | * | ) internal view returns (int256) {
468 | * | if (pnl < 0) {
469 | * | return pnl;
470 | | }
471 | |
472 | * | uint256 maxPnlFactor = getMaxPnlFactor(
473 | * | dataStore,
474 | * | pnlFactorType,
475 | * | market,
476 | * | isLong
477 | | );
478 | * | int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();
479 | |
480 | * | return pnl > maxPnl ? maxPnl : pnl;
481 | | }
482 | |
483 | | // @dev get the pending pnl for a market
484 | | // @param dataStore DataStore
485 | | // @param market the market to check
486 | | // @param longToken the long token of the market
487 | | // @param shortToken the short token of the market
488 | | // @param indexTokenPrice the price of the index token
489 | | // @param isLong whether to check for the long or short side
490 | | // @param maximize whether to maximize or minimize the pnl
491 | | function getPnl(
492 | | DataStore dataStore,
493 | | Market.Props memory market,
494 | | uint256 indexTokenPrice,
495 | | bool isLong,
496 | | bool maximize
497 | | ) internal view returns (int256) {
498 | | Price.Props memory _indexTokenPrice = Price.Props(
499 | | indexTokenPrice,
500 | | indexTokenPrice
501 | | );
502 | |
503 | | return getPnl(dataStore, market, _indexTokenPrice, isLong, maximize);
504 | | }
505 | |
506 | | // @dev get the pending pnl for a market for either longs or shorts
507 | | // @param dataStore DataStore
508 | | // @param market the market to check
509 | | // @param longToken the long token of the market
510 | | // @param shortToken the short token of the market
511 | | // @param indexTokenPrice the price of the index token
512 | | // @param isLong whether to get the pnl for longs or shorts
513 | | // @param maximize whether to maximize or minimize the net pnl
514 | | // @return the pending pnl for a market for either longs or shorts
515 | * | function getPnl(
516 | | DataStore dataStore,
517 | | Market.Props memory market,
518 | | Price.Props memory indexTokenPrice,
519 | | bool isLong,
520 | | bool maximize
521 | * | ) internal view returns (int256) {
522 | * | int256 openInterest = getOpenInterest(dataStore, market, isLong)
523 | | .toInt256();
524 | * | uint256 openInterestInTokens = getOpenInterestInTokens(
525 | * | dataStore,
526 | * | market,
527 | * | isLong
528 | | );
529 | * | if (openInterest == 0 || openInterestInTokens == 0) {
530 | * | return 0;
531 | | }
532 | |
533 | * | uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);
534 | |
535 | | // openInterest is the cost of all positions, openInterestValue is the current worth of all positions
536 | * | int256 openInterestValue = (openInterestInTokens * price).toInt256();
537 | * | int256 pnl = isLong
538 | * | ? openInterestValue - openInterest
539 | * | : openInterest - openInterestValue;
540 | |
541 | * | return pnl;
542 | | }
543 | |
544 | | // @dev get the amount of tokens in the pool
545 | | // @param dataStore DataStore
546 | | // @param market the market to check
547 | | // @param token the token to check
548 | | // @return the amount of tokens in the pool
549 | * | function getPoolAmount(
550 | | DataStore dataStore,
551 | | Market.Props memory market,
552 | | address token
553 | * | ) internal view returns (uint256) {
554 | | /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */
555 | | // if the longToken and shortToken are the same, return half of the token amount, so that
556 | | // calculations of pool value, etc would be correct
557 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
558 | * | return
559 | * | dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) /
560 | * | divisor;
561 | | }
562 | |
563 | | // @dev get the max amount of tokens allowed to be in the pool
564 | | // @param dataStore DataStore
565 | | // @param market the market to check
566 | | // @param token the token to check
567 | | // @return the max amount of tokens that are allowed in the pool
568 | * | function getMaxPoolAmount(
569 | | DataStore dataStore,
570 | | address market,
571 | | address token
572 | * | ) internal view returns (uint256) {
573 | * | return dataStore.getUint(Keys.maxPoolAmountKey(market, token));
574 | | }
575 | |
576 | * | function getMaxPoolUsdForDeposit(
577 | | DataStore dataStore,
578 | | address market,
579 | | address token
580 | * | ) internal view returns (uint256) {
581 | * | return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));
582 | | }
583 | |
584 | | function getUsageFactor(
585 | | DataStore dataStore,
586 | | Market.Props memory market,
587 | | bool isLong,
588 | | uint256 reservedUsd,
589 | | uint256 poolUsd
590 | | ) internal view returns (uint256) {
591 | | uint256 reserveFactor = getOpenInterestReserveFactor(
592 | | dataStore,
593 | | market.marketToken,
594 | | isLong
595 | | );
596 | | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
597 | | uint256 reserveUsageFactor = Precision.toFactor(
598 | | reservedUsd,
599 | | maxReservedUsd
600 | | );
601 | |
602 | | uint256 maxOpenInterest = getMaxOpenInterest(
603 | | dataStore,
604 | | market.marketToken,
605 | | isLong
606 | | );
607 | | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
608 | | uint256 openInterestUsageFactor = Precision.toFactor(
609 | | openInterest,
610 | | maxOpenInterest
611 | | );
612 | |
613 | | return
614 | | reserveUsageFactor > openInterestUsageFactor
615 | | ? reserveUsageFactor
616 | | : openInterestUsageFactor;
617 | | }
618 | |
619 | | // @dev get the max open interest allowed for the market
620 | | // @param dataStore DataStore
621 | | // @param market the market to check
622 | | // @param isLong whether this is for the long or short side
623 | | // @return the max open interest allowed for the market
624 | * | function getMaxOpenInterest(
625 | | DataStore dataStore,
626 | | address market,
627 | | bool isLong
628 | * | ) internal view returns (uint256) {
629 | * | return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));
630 | | }
631 | |
632 | | // @dev increment the claimable collateral amount
633 | | // @param dataStore DataStore
634 | | // @param eventEmitter EventEmitter
635 | | // @param market the market to increment the claimable collateral for
636 | | // @param token the claimable token
637 | | // @param account the account to increment the claimable collateral for
638 | | // @param delta the amount to increment
639 | | function incrementClaimableCollateralAmount(
640 | | DataStore dataStore,
641 | | EventEmitter eventEmitter,
642 | | address market,
643 | | address token,
644 | | address account,
645 | | uint256 delta
646 | | ) internal {
647 | | uint256 divisor = dataStore.getUint(
648 | | Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR
649 | | );
650 | | uint256 timeKey = Chain.currentTimestamp() / divisor;
651 | |
652 | | uint256 nextValue = dataStore.incrementUint(
653 | | Keys.claimableCollateralAmountKey(market, token, timeKey, account),
654 | | delta
655 | | );
656 | |
657 | | uint256 nextPoolValue = dataStore.incrementUint(
658 | | Keys.claimableCollateralAmountKey(market, token),
659 | | delta
660 | | );
661 | |
662 | | MarketEventUtils.emitClaimableCollateralUpdated(
663 | | eventEmitter,
664 | | market,
665 | | token,
666 | | timeKey,
667 | | account,
668 | | delta,
669 | | nextValue,
670 | | nextPoolValue
671 | | );
672 | | }
673 | |
674 | | // @dev increment the claimable funding amount
675 | | // @param dataStore DataStore
676 | | // @param eventEmitter EventEmitter
677 | | // @param market the trading market
678 | | // @param token the claimable token
679 | | // @param account the account to increment for
680 | | // @param delta the amount to increment
681 | * | function incrementClaimableFundingAmount(
682 | | DataStore dataStore,
683 | | EventEmitter eventEmitter,
684 | | address market,
685 | | address token,
686 | | address account,
687 | | uint256 delta
688 | * | ) internal {
689 | * | uint256 nextValue = dataStore.incrementUint(
690 | * | Keys.claimableFundingAmountKey(market, token, account),
691 | * | delta
692 | | );
693 | |
694 | * | uint256 nextPoolValue = dataStore.incrementUint(
695 | * | Keys.claimableFundingAmountKey(market, token),
696 | * | delta
697 | | );
698 | |
699 | * | MarketEventUtils.emitClaimableFundingUpdated(
700 | * | eventEmitter,
701 | * | market,
702 | * | token,
703 | * | account,
704 | * | delta,
705 | * | nextValue,
706 | * | nextPoolValue
707 | | );
708 | | }
709 | |
710 | | // @dev claim funding fees
711 | | // @param dataStore DataStore
712 | | // @param eventEmitter EventEmitter
713 | | // @param market the market to claim for
714 | | // @param token the token to claim
715 | | // @param account the account to claim for
716 | | // @param receiver the receiver to send the amount to
717 | * | function claimFundingFees(
718 | | DataStore dataStore,
719 | | EventEmitter eventEmitter,
720 | | address market,
721 | | address token,
722 | | address account,
723 | | address receiver
724 | * | ) internal returns (uint256) {
725 | * | bytes32 key = Keys.claimableFundingAmountKey(market, token, account);
726 | |
727 | * | uint256 claimableAmount = dataStore.getUint(key);
728 | * | dataStore.setUint(key, 0);
729 | |
730 | * | uint256 nextPoolValue = dataStore.decrementUint(
731 | * | Keys.claimableFundingAmountKey(market, token),
732 | * | claimableAmount
733 | | );
734 | |
735 | * | MarketToken(payable(market)).transferOut(
736 | * | token,
737 | * | receiver,
738 | * | claimableAmount
739 | | );
740 | |
741 | * | validateMarketTokenBalance(dataStore, market);
742 | |
743 | * | MarketEventUtils.emitFundingFeesClaimed(
744 | * | eventEmitter,
745 | * | market,
746 | * | token,
747 | * | account,
748 | * | receiver,
749 | * | claimableAmount,
750 | * | nextPoolValue
751 | | );
752 | |
753 | * | return claimableAmount;
754 | | }
755 | |
756 | | // @dev claim collateral
757 | | // @param dataStore DataStore
758 | | // @param eventEmitter EventEmitter
759 | | // @param market the market to claim for
760 | | // @param token the token to claim
761 | | // @param timeKey the time key
762 | | // @param account the account to claim for
763 | | // @param receiver the receiver to send the amount to
764 | | function claimCollateral(
765 | | DataStore dataStore,
766 | | EventEmitter eventEmitter,
767 | | address market,
768 | | address token,
769 | | uint256 timeKey,
770 | | address account,
771 | | address receiver
772 | | ) internal returns (uint256) {
773 | | uint256 claimableAmount = dataStore.getUint(
774 | | Keys.claimableCollateralAmountKey(market, token, timeKey, account)
775 | | );
776 | |
777 | | uint256 claimableFactor;
778 | |
779 | | {
780 | | uint256 claimableFactorForTime = dataStore.getUint(
781 | | Keys.claimableCollateralFactorKey(market, token, timeKey)
782 | | );
783 | | uint256 claimableFactorForAccount = dataStore.getUint(
784 | | Keys.claimableCollateralFactorKey(
785 | | market,
786 | | token,
787 | | timeKey,
788 | | account
789 | | )
790 | | );
791 | | claimableFactor = claimableFactorForTime > claimableFactorForAccount
792 | | ? claimableFactorForTime
793 | | : claimableFactorForAccount;
794 | | }
795 | |
796 | | if (claimableFactor > Precision.FLOAT_PRECISION) {
797 | | revert Errors.InvalidClaimableFactor(claimableFactor);
798 | | }
799 | |
800 | | uint256 claimedAmount = dataStore.getUint(
801 | | Keys.claimedCollateralAmountKey(market, token, timeKey, account)
802 | | );
803 | |
804 | | uint256 adjustedClaimableAmount = Precision.applyFactor(
805 | | claimableAmount,
806 | | claimableFactor
807 | | );
808 | | if (adjustedClaimableAmount <= claimedAmount) {
809 | | revert Errors.CollateralAlreadyClaimed(
810 | | adjustedClaimableAmount,
811 | | claimedAmount
812 | | );
813 | | }
814 | |
815 | | uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;
816 | |
817 | | dataStore.setUint(
818 | | Keys.claimedCollateralAmountKey(market, token, timeKey, account),
819 | | adjustedClaimableAmount
820 | | );
821 | |
822 | | uint256 nextPoolValue = dataStore.decrementUint(
823 | | Keys.claimableCollateralAmountKey(market, token),
824 | | amountToBeClaimed
825 | | );
826 | |
827 | | MarketToken(payable(market)).transferOut(
828 | | token,
829 | | receiver,
830 | | amountToBeClaimed
831 | | );
832 | |
833 | | validateMarketTokenBalance(dataStore, market);
834 | |
835 | | MarketEventUtils.emitCollateralClaimed(
836 | | eventEmitter,
837 | | market,
838 | | token,
839 | | timeKey,
840 | | account,
841 | | receiver,
842 | | amountToBeClaimed,
843 | | nextPoolValue
844 | | );
845 | |
846 | | return amountToBeClaimed;
847 | | }
848 | |
849 | | // @dev apply a delta to the pool amount
850 | | // validatePoolAmount is not called in this function since applyDeltaToPoolAmount
851 | | // is called when receiving fees
852 | | // @param dataStore DataStore
853 | | // @param eventEmitter EventEmitter
854 | | // @param market the market to apply to
855 | | // @param token the token to apply to
856 | | // @param delta the delta amount
857 | * | function applyDeltaToPoolAmount(
858 | | DataStore dataStore,
859 | | EventEmitter eventEmitter,
860 | | Market.Props memory market,
861 | | address token,
862 | | int256 delta
863 | * | ) internal returns (uint256) {
864 | * | uint256 nextValue = dataStore.applyDeltaToUint(
865 | * | Keys.poolAmountKey(market.marketToken, token),
866 | * | delta,
867 | | "Invalid state, negative poolAmount"
868 | | );
869 | |
870 | * | applyDeltaToVirtualInventoryForSwaps(
871 | * | dataStore,
872 | * | eventEmitter,
873 | * | market,
874 | * | token,
875 | * | delta
876 | | );
877 | |
878 | * | MarketEventUtils.emitPoolAmountUpdated(
879 | * | eventEmitter,
880 | * | market.marketToken,
881 | * | token,
882 | * | delta,
883 | * | nextValue
884 | | );
885 | |
886 | * | return nextValue;
887 | | }
888 | |
889 | * | function getAdjustedSwapImpactFactor(
890 | | DataStore dataStore,
891 | | address market,
892 | | bool isPositive
893 | * | ) internal view returns (uint256) {
894 | * | (
895 | * | uint256 positiveImpactFactor,
896 | * | uint256 negativeImpactFactor
897 | * | ) = getAdjustedSwapImpactFactors(dataStore, market);
898 | |
899 | * | return isPositive ? positiveImpactFactor : negativeImpactFactor;
900 | | }
901 | |
902 | * | function getAdjustedSwapImpactFactors(
903 | | DataStore dataStore,
904 | | address market
905 | * | ) internal view returns (uint256, uint256) {
906 | * | uint256 positiveImpactFactor = dataStore.getUint(
907 | * | Keys.swapImpactFactorKey(market, true)
908 | | );
909 | * | uint256 negativeImpactFactor = dataStore.getUint(
910 | * | Keys.swapImpactFactorKey(market, false)
911 | | );
912 | |
913 | | // if the positive impact factor is more than the negative impact factor, positions could be opened
914 | | // and closed immediately for a profit if the difference is sufficient to cover the position fees
915 | * | if (positiveImpactFactor > negativeImpactFactor) {
916 | | positiveImpactFactor = negativeImpactFactor;
917 | | }
918 | |
919 | * | return (positiveImpactFactor, negativeImpactFactor);
920 | | }
921 | |
922 | * | function getAdjustedPositionImpactFactor(
923 | | DataStore dataStore,
924 | | address market,
925 | | bool isPositive
926 | * | ) internal view returns (uint256) {
927 | * | (
928 | * | uint256 positiveImpactFactor,
929 | * | uint256 negativeImpactFactor
930 | * | ) = getAdjustedPositionImpactFactors(dataStore, market);
931 | |
932 | * | return isPositive ? positiveImpactFactor : negativeImpactFactor;
933 | | }
934 | |
935 | * | function getAdjustedPositionImpactFactors(
936 | | DataStore dataStore,
937 | | address market
938 | * | ) internal view returns (uint256, uint256) {
939 | * | uint256 positiveImpactFactor = dataStore.getUint(
940 | * | Keys.positionImpactFactorKey(market, true)
941 | | );
942 | * | uint256 negativeImpactFactor = dataStore.getUint(
943 | * | Keys.positionImpactFactorKey(market, false)
944 | | );
945 | |
946 | | // if the positive impact factor is more than the negative impact factor, positions could be opened
947 | | // and closed immediately for a profit if the difference is sufficient to cover the position fees
948 | * | if (positiveImpactFactor > negativeImpactFactor) {
949 | | positiveImpactFactor = negativeImpactFactor;
950 | | }
951 | |
952 | * | return (positiveImpactFactor, negativeImpactFactor);
953 | | }
954 | |
955 | | // @dev cap the input priceImpactUsd by the available amount in the position
956 | | // impact pool and the max positive position impact factor
957 | | // @param dataStore DataStore
958 | | // @param market the trading market
959 | | // @param tokenPrice the price of the token
960 | | // @param priceImpactUsd the calculated USD price impact
961 | | // @return the capped priceImpactUsd
962 | * | function getCappedPositionImpactUsd(
963 | | DataStore dataStore,
964 | | address market,
965 | | Price.Props memory indexTokenPrice,
966 | | int256 priceImpactUsd,
967 | | uint256 sizeDeltaUsd
968 | * | ) internal view returns (int256) {
969 | * | if (priceImpactUsd < 0) {
970 | * | return priceImpactUsd;
971 | | }
972 | |
973 | * | uint256 impactPoolAmount = getPositionImpactPoolAmount(
974 | * | dataStore,
975 | * | market
976 | | );
977 | * | int256 maxPriceImpactUsdBasedOnImpactPool = (impactPoolAmount *
978 | * | indexTokenPrice.min).toInt256();
979 | |
980 | * | if (priceImpactUsd > maxPriceImpactUsdBasedOnImpactPool) {
981 | * | priceImpactUsd = maxPriceImpactUsdBasedOnImpactPool;
982 | | }
983 | |
984 | * | uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(
985 | * | dataStore,
986 | * | market,
987 | * | true
988 | | );
989 | * | int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision
990 | * | .applyFactor(sizeDeltaUsd, maxPriceImpactFactor)
991 | | .toInt256();
992 | |
993 | * | if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {
994 | * | priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;
995 | | }
996 | |
997 | * | return priceImpactUsd;
998 | | }
999 | |
1000 | | // @dev get the position impact pool amount
1001 | | // @param dataStore DataStore
1002 | | // @param market the market to check
1003 | | // @return the position impact pool amount
1004 | * | function getPositionImpactPoolAmount(
1005 | | DataStore dataStore,
1006 | | address market
1007 | * | ) internal view returns (uint256) {
1008 | * | return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));
1009 | | }
1010 | |
1011 | | // @dev get the swap impact pool amount
1012 | | // @param dataStore DataStore
1013 | | // @param market the market to check
1014 | | // @param token the token to check
1015 | | // @return the swap impact pool amount
1016 | * | function getSwapImpactPoolAmount(
1017 | | DataStore dataStore,
1018 | | address market,
1019 | | address token
1020 | * | ) internal view returns (uint256) {
1021 | * | return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));
1022 | | }
1023 | |
1024 | | // @dev apply a delta to the swap impact pool
1025 | | // @param dataStore DataStore
1026 | | // @param eventEmitter EventEmitter
1027 | | // @param market the market to apply to
1028 | | // @param token the token to apply to
1029 | | // @param delta the delta amount
1030 | * | function applyDeltaToSwapImpactPool(
1031 | | DataStore dataStore,
1032 | | EventEmitter eventEmitter,
1033 | | address market,
1034 | | address token,
1035 | | int256 delta
1036 | * | ) internal returns (uint256) {
1037 | * | uint256 nextValue = dataStore.applyBoundedDeltaToUint(
1038 | * | Keys.swapImpactPoolAmountKey(market, token),
1039 | * | delta
1040 | | );
1041 | |
1042 | * | MarketEventUtils.emitSwapImpactPoolAmountUpdated(
1043 | * | eventEmitter,
1044 | * | market,
1045 | * | token,
1046 | * | delta,
1047 | * | nextValue
1048 | | );
1049 | |
1050 | * | return nextValue;
1051 | | }
1052 | |
1053 | | // @dev apply a delta to the position impact pool
1054 | | // @param dataStore DataStore
1055 | | // @param eventEmitter EventEmitter
1056 | | // @param market the market to apply to
1057 | | // @param delta the delta amount
1058 | * | function applyDeltaToPositionImpactPool(
1059 | | DataStore dataStore,
1060 | | EventEmitter eventEmitter,
1061 | | address market,
1062 | | int256 delta
1063 | * | ) internal returns (uint256) {
1064 | * | uint256 nextValue = dataStore.applyBoundedDeltaToUint(
1065 | * | Keys.positionImpactPoolAmountKey(market),
1066 | * | delta
1067 | | );
1068 | |
1069 | * | MarketEventUtils.emitPositionImpactPoolAmountUpdated(
1070 | * | eventEmitter,
1071 | * | market,
1072 | * | delta,
1073 | * | nextValue
1074 | | );
1075 | |
1076 | * | return nextValue;
1077 | | }
1078 | |
1079 | | // @dev apply a delta to the open interest
1080 | | // @param dataStore DataStore
1081 | | // @param eventEmitter EventEmitter
1082 | | // @param market the market to apply to
1083 | | // @param collateralToken the collateralToken to apply to
1084 | | // @param isLong whether to apply to the long or short side
1085 | | // @param delta the delta amount
1086 | * | function applyDeltaToOpenInterest(
1087 | | DataStore dataStore,
1088 | | EventEmitter eventEmitter,
1089 | | Market.Props memory market,
1090 | | address collateralToken,
1091 | | bool isLong,
1092 | | int256 delta
1093 | * | ) internal returns (uint256) {
1094 | * | if (market.indexToken == address(0)) {
1095 | | revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(
1096 | | market.marketToken
1097 | | );
1098 | | }
1099 | |
1100 | * | uint256 nextValue = dataStore.applyDeltaToUint(
1101 | * | Keys.openInterestKey(market.marketToken, collateralToken, isLong),
1102 | * | delta,
1103 | | "Invalid state: negative open interest"
1104 | | );
1105 | |
1106 | | // if the open interest for longs is increased then tokens were virtually bought from the pool
1107 | | // so the virtual inventory should be decreased
1108 | | // if the open interest for longs is decreased then tokens were virtually sold to the pool
1109 | | // so the virtual inventory should be increased
1110 | | // if the open interest for shorts is increased then tokens were virtually sold to the pool
1111 | | // so the virtual inventory should be increased
1112 | | // if the open interest for shorts is decreased then tokens were virtually bought from the pool
1113 | | // so the virtual inventory should be decreased
1114 | * | applyDeltaToVirtualInventoryForPositions(
1115 | * | dataStore,
1116 | * | eventEmitter,
1117 | * | market.indexToken,
1118 | * | isLong ? -delta : delta
1119 | | );
1120 | |
1121 | * | if (delta > 0) {
1122 | * | validateOpenInterest(dataStore, market, isLong);
1123 | | }
1124 | |
1125 | * | MarketEventUtils.emitOpenInterestUpdated(
1126 | * | eventEmitter,
1127 | * | market.marketToken,
1128 | * | collateralToken,
1129 | * | isLong,
1130 | * | delta,
1131 | * | nextValue
1132 | | );
1133 | |
1134 | * | return nextValue;
1135 | | }
1136 | |
1137 | | // @dev apply a delta to the open interest in tokens
1138 | | // @param dataStore DataStore
1139 | | // @param eventEmitter EventEmitter
1140 | | // @param market the market to apply to
1141 | | // @param collateralToken the collateralToken to apply to
1142 | | // @param isLong whether to apply to the long or short side
1143 | | // @param delta the delta amount
1144 | * | function applyDeltaToOpenInterestInTokens(
1145 | | DataStore dataStore,
1146 | | EventEmitter eventEmitter,
1147 | | address market,
1148 | | address collateralToken,
1149 | | bool isLong,
1150 | | int256 delta
1151 | * | ) internal returns (uint256) {
1152 | * | uint256 nextValue = dataStore.applyDeltaToUint(
1153 | * | Keys.openInterestInTokensKey(market, collateralToken, isLong),
1154 | * | delta,
1155 | | "Invalid state: negative open interest in tokens"
1156 | | );
1157 | |
1158 | * | MarketEventUtils.emitOpenInterestInTokensUpdated(
1159 | * | eventEmitter,
1160 | * | market,
1161 | * | collateralToken,
1162 | * | isLong,
1163 | * | delta,
1164 | * | nextValue
1165 | | );
1166 | |
1167 | * | return nextValue;
1168 | | }
1169 | |
1170 | | // @dev apply a delta to the collateral sum
1171 | | // @param dataStore DataStore
1172 | | // @param eventEmitter EventEmitter
1173 | | // @param market the market to apply to
1174 | | // @param collateralToken the collateralToken to apply to
1175 | | // @param isLong whether to apply to the long or short side
1176 | | // @param delta the delta amount
1177 | * | function applyDeltaToCollateralSum(
1178 | | DataStore dataStore,
1179 | | EventEmitter eventEmitter,
1180 | | address market,
1181 | | address collateralToken,
1182 | | bool isLong,
1183 | | int256 delta
1184 | * | ) internal returns (uint256) {
1185 | * | uint256 nextValue = dataStore.applyDeltaToUint(
1186 | * | Keys.collateralSumKey(market, collateralToken, isLong),
1187 | * | delta,
1188 | | "Invalid state: negative collateralSum"
1189 | | );
1190 | |
1191 | * | MarketEventUtils.emitCollateralSumUpdated(
1192 | * | eventEmitter,
1193 | * | market,
1194 | * | collateralToken,
1195 | * | isLong,
1196 | * | delta,
1197 | * | nextValue
1198 | | );
1199 | |
1200 | * | return nextValue;
1201 | | }
1202 | |
1203 | | // @dev update the funding state
1204 | | // @param dataStore DataStore
1205 | | // @param market the market to update
1206 | | // @param prices the prices of the market tokens
1207 | * | function updateFundingState(
1208 | | DataStore dataStore,
1209 | | EventEmitter eventEmitter,
1210 | | Market.Props memory market,
1211 | | MarketPrices memory prices
1212 | * | ) internal {
1213 | * | GetNextFundingAmountPerSizeResult
1214 | * | memory result = getNextFundingAmountPerSize(
1215 | * | dataStore,
1216 | * | market,
1217 | * | prices
1218 | | );
1219 | |
1220 | * | applyDeltaToFundingFeeAmountPerSize(
1221 | * | dataStore,
1222 | * | eventEmitter,
1223 | * | market.marketToken,
1224 | * | market.longToken,
1225 | * | true,
1226 | * | result.fundingFeeAmountPerSizeDelta.long.longToken
1227 | | );
1228 | |
1229 | * | applyDeltaToFundingFeeAmountPerSize(
1230 | * | dataStore,
1231 | * | eventEmitter,
1232 | * | market.marketToken,
1233 | * | market.longToken,
1234 | * | false,
1235 | * | result.fundingFeeAmountPerSizeDelta.short.longToken
1236 | | );
1237 | |
1238 | * | applyDeltaToFundingFeeAmountPerSize(
1239 | * | dataStore,
1240 | * | eventEmitter,
1241 | * | market.marketToken,
1242 | * | market.shortToken,
1243 | * | true,
1244 | * | result.fundingFeeAmountPerSizeDelta.long.shortToken
1245 | | );
1246 | |
1247 | * | applyDeltaToFundingFeeAmountPerSize(
1248 | * | dataStore,
1249 | * | eventEmitter,
1250 | * | market.marketToken,
1251 | * | market.shortToken,
1252 | * | false,
1253 | * | result.fundingFeeAmountPerSizeDelta.short.shortToken
1254 | | );
1255 | |
1256 | * | applyDeltaToClaimableFundingAmountPerSize(
1257 | * | dataStore,
1258 | * | eventEmitter,
1259 | * | market.marketToken,
1260 | * | market.longToken,
1261 | * | true,
1262 | * | result.claimableFundingAmountPerSizeDelta.long.longToken
1263 | | );
1264 | |
1265 | * | applyDeltaToClaimableFundingAmountPerSize(
1266 | * | dataStore,
1267 | * | eventEmitter,
1268 | * | market.marketToken,
1269 | * | market.longToken,
1270 | * | false,
1271 | * | result.claimableFundingAmountPerSizeDelta.short.longToken
1272 | | );
1273 | |
1274 | * | applyDeltaToClaimableFundingAmountPerSize(
1275 | * | dataStore,
1276 | * | eventEmitter,
1277 | * | market.marketToken,
1278 | * | market.shortToken,
1279 | * | true,
1280 | * | result.claimableFundingAmountPerSizeDelta.long.shortToken
1281 | | );
1282 | |
1283 | * | applyDeltaToClaimableFundingAmountPerSize(
1284 | * | dataStore,
1285 | * | eventEmitter,
1286 | * | market.marketToken,
1287 | * | market.shortToken,
1288 | * | false,
1289 | * | result.claimableFundingAmountPerSizeDelta.short.shortToken
1290 | | );
1291 | |
1292 | * | setSavedFundingFactorPerSecond(
1293 | * | dataStore,
1294 | * | market.marketToken,
1295 | * | result.nextSavedFundingFactorPerSecond
1296 | | );
1297 | |
1298 | * | dataStore.setUint(
1299 | * | Keys.fundingUpdatedAtKey(market.marketToken),
1300 | * | Chain.currentTimestamp()
1301 | | );
1302 | | }
1303 | |
1304 | | // @dev get the next funding amount per size values
1305 | | // @param dataStore DataStore
1306 | | // @param prices the prices of the market tokens
1307 | | // @param market the market to update
1308 | | // @param longToken the market's long token
1309 | | // @param shortToken the market's short token
1310 | * | function getNextFundingAmountPerSize(
1311 | | DataStore dataStore,
1312 | | Market.Props memory market,
1313 | | MarketPrices memory prices
1314 | * | ) internal view returns (GetNextFundingAmountPerSizeResult memory) {
1315 | * | GetNextFundingAmountPerSizeResult memory result;
1316 | * | GetNextFundingAmountPerSizeCache memory cache;
1317 | |
1318 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
1319 | |
1320 | | // get the open interest values by long / short and by collateral used
1321 | * | cache.openInterest.long.longToken = getOpenInterest(
1322 | * | dataStore,
1323 | * | market.marketToken,
1324 | * | market.longToken,
1325 | * | true,
1326 | * | divisor
1327 | | );
1328 | * | cache.openInterest.long.shortToken = getOpenInterest(
1329 | * | dataStore,
1330 | * | market.marketToken,
1331 | * | market.shortToken,
1332 | * | true,
1333 | * | divisor
1334 | | );
1335 | * | cache.openInterest.short.longToken = getOpenInterest(
1336 | * | dataStore,
1337 | * | market.marketToken,
1338 | * | market.longToken,
1339 | * | false,
1340 | * | divisor
1341 | | );
1342 | * | cache.openInterest.short.shortToken = getOpenInterest(
1343 | * | dataStore,
1344 | * | market.marketToken,
1345 | * | market.shortToken,
1346 | * | false,
1347 | * | divisor
1348 | | );
1349 | |
1350 | | // sum the open interest values to get the total long and short open interest values
1351 | * | cache.longOpenInterest =
1352 | * | cache.openInterest.long.longToken +
1353 | * | cache.openInterest.long.shortToken;
1354 | * | cache.shortOpenInterest =
1355 | * | cache.openInterest.short.longToken +
1356 | * | cache.openInterest.short.shortToken;
1357 | |
1358 | | // if either long or short open interest is zero, then funding should not be updated
1359 | | // as there would not be any user to pay the funding to
1360 | * | if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {
1361 | * | return result;
1362 | | }
1363 | |
1364 | | // if the blockchain is not progressing / a market is disabled, funding fees
1365 | | // will continue to accumulate
1366 | | // this should be a rare occurrence so funding fees are not adjusted for this case
1367 | * | cache.durationInSeconds = getSecondsSinceFundingUpdated(
1368 | * | dataStore,
1369 | * | market.marketToken
1370 | | );
1371 | |
1372 | * | cache.sizeOfLargerSide = cache.longOpenInterest >
1373 | * | cache.shortOpenInterest
1374 | * | ? cache.longOpenInterest
1375 | * | : cache.shortOpenInterest;
1376 | |
1377 | * | (
1378 | * | result.fundingFactorPerSecond,
1379 | * | result.longsPayShorts,
1380 | * | result.nextSavedFundingFactorPerSecond
1381 | * | ) = getNextFundingFactorPerSecond(
1382 | * | dataStore,
1383 | * | market.marketToken,
1384 | * | cache.longOpenInterest,
1385 | * | cache.shortOpenInterest,
1386 | * | cache.durationInSeconds
1387 | | );
1388 | |
1389 | | // for single token markets, if there is $200,000 long open interest
1390 | | // and $100,000 short open interest and if the fundingUsd is $8:
1391 | | // fundingUsdForLongCollateral: $4
1392 | | // fundingUsdForShortCollateral: $4
1393 | | // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000
1394 | | // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000
1395 | | // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000
1396 | | // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000
1397 | | //
1398 | | // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the
1399 | | // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2
1400 | | //
1401 | | // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice:
1402 | | // 4 / 100,000 + 4 / 100,000 = 8 / 100,000
1403 | | //
1404 | | // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged
1405 | | //
1406 | | // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice:
1407 | | // 4 / 100,000 + 4 / 100,000 = 8 / 100,000
1408 | | //
1409 | | // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize
1410 | | // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken
1411 | | //
1412 | | // since both these values will be duplicated, the amount claimable would be:
1413 | | // (8 / 100,000 + 8 / 100,000) * 100,000 = $16
1414 | | //
1415 | | // due to these, the fundingUsd should be divided by the divisor
1416 | |
1417 | * | cache.fundingUsd = Precision.applyFactor(
1418 | * | cache.sizeOfLargerSide,
1419 | * | cache.durationInSeconds * result.fundingFactorPerSecond
1420 | | );
1421 | * | cache.fundingUsd = cache.fundingUsd / divisor;
1422 | |
1423 | | // split the fundingUsd value by long and short collateral
1424 | | // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest
1425 | | // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees
1426 | | // should be paid from long positions using short collateral
1427 | | // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral
1428 | * | if (result.longsPayShorts) {
1429 | * | cache.fundingUsdForLongCollateral = Precision.mulDiv(
1430 | * | cache.fundingUsd,
1431 | * | cache.openInterest.long.longToken,
1432 | * | cache.longOpenInterest
1433 | | );
1434 | * | cache.fundingUsdForShortCollateral = Precision.mulDiv(
1435 | * | cache.fundingUsd,
1436 | * | cache.openInterest.long.shortToken,
1437 | * | cache.longOpenInterest
1438 | | );
1439 | | } else {
1440 | * | cache.fundingUsdForLongCollateral = Precision.mulDiv(
1441 | * | cache.fundingUsd,
1442 | * | cache.openInterest.short.longToken,
1443 | * | cache.shortOpenInterest
1444 | | );
1445 | * | cache.fundingUsdForShortCollateral = Precision.mulDiv(
1446 | * | cache.fundingUsd,
1447 | * | cache.openInterest.short.shortToken,
1448 | * | cache.shortOpenInterest
1449 | | );
1450 | | }
1451 | |
1452 | | // calculate the change in funding amount per size values
1453 | | // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000
1454 | | // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1
1455 | | // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1
1456 | * | if (result.longsPayShorts) {
1457 | | // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received
1458 | | // positions only pay funding in the position's collateral token
1459 | | // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral
1460 | | // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral
1461 | * | result
1462 | | .fundingFeeAmountPerSizeDelta
1463 | | .long
1464 | * | .longToken = getFundingAmountPerSizeDelta(
1465 | * | cache.fundingUsdForLongCollateral,
1466 | * | cache.openInterest.long.longToken,
1467 | * | prices.longTokenPrice.max,
1468 | * | true // roundUpMagnitude
1469 | | );
1470 | |
1471 | * | result
1472 | | .fundingFeeAmountPerSizeDelta
1473 | | .long
1474 | * | .shortToken = getFundingAmountPerSizeDelta(
1475 | * | cache.fundingUsdForShortCollateral,
1476 | * | cache.openInterest.long.shortToken,
1477 | * | prices.shortTokenPrice.max,
1478 | * | true // roundUpMagnitude
1479 | | );
1480 | |
1481 | | // positions receive funding in both the longToken and shortToken
1482 | | // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest
1483 | * | result
1484 | | .claimableFundingAmountPerSizeDelta
1485 | | .short
1486 | * | .longToken = getFundingAmountPerSizeDelta(
1487 | * | cache.fundingUsdForLongCollateral,
1488 | * | cache.shortOpenInterest,
1489 | * | prices.longTokenPrice.max,
1490 | * | false // roundUpMagnitude
1491 | | );
1492 | |
1493 | * | result
1494 | | .claimableFundingAmountPerSizeDelta
1495 | | .short
1496 | * | .shortToken = getFundingAmountPerSizeDelta(
1497 | * | cache.fundingUsdForShortCollateral,
1498 | * | cache.shortOpenInterest,
1499 | * | prices.shortTokenPrice.max,
1500 | * | false // roundUpMagnitude
1501 | | );
1502 | | } else {
1503 | | // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received
1504 | | // positions only pay funding in the position's collateral token
1505 | | // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral
1506 | | // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral
1507 | * | result
1508 | | .fundingFeeAmountPerSizeDelta
1509 | | .short
1510 | * | .longToken = getFundingAmountPerSizeDelta(
1511 | * | cache.fundingUsdForLongCollateral,
1512 | * | cache.openInterest.short.longToken,
1513 | * | prices.longTokenPrice.max,
1514 | * | true // roundUpMagnitude
1515 | | );
1516 | |
1517 | * | result
1518 | | .fundingFeeAmountPerSizeDelta
1519 | | .short
1520 | * | .shortToken = getFundingAmountPerSizeDelta(
1521 | * | cache.fundingUsdForShortCollateral,
1522 | * | cache.openInterest.short.shortToken,
1523 | * | prices.shortTokenPrice.max,
1524 | * | true // roundUpMagnitude
1525 | | );
1526 | |
1527 | | // positions receive funding in both the longToken and shortToken
1528 | | // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest
1529 | * | result
1530 | | .claimableFundingAmountPerSizeDelta
1531 | | .long
1532 | * | .longToken = getFundingAmountPerSizeDelta(
1533 | * | cache.fundingUsdForLongCollateral,
1534 | * | cache.longOpenInterest,
1535 | * | prices.longTokenPrice.max,
1536 | * | false // roundUpMagnitude
1537 | | );
1538 | |
1539 | * | result
1540 | | .claimableFundingAmountPerSizeDelta
1541 | | .long
1542 | * | .shortToken = getFundingAmountPerSizeDelta(
1543 | * | cache.fundingUsdForShortCollateral,
1544 | * | cache.longOpenInterest,
1545 | * | prices.shortTokenPrice.max,
1546 | * | false // roundUpMagnitude
1547 | | );
1548 | | }
1549 | |
1550 | * | return result;
1551 | | }
1552 | |
1553 | | // @dev get the next funding factor per second
1554 | | // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped
1555 | | // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents
1556 | | // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip
1557 | | // if it is bound by minFundingFactorPerSecond
1558 | | // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond
1559 | | // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond
1560 | | // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond
1561 | * | function getNextFundingFactorPerSecond(
1562 | | DataStore dataStore,
1563 | | address market,
1564 | | uint256 longOpenInterest,
1565 | | uint256 shortOpenInterest,
1566 | | uint256 durationInSeconds
1567 | * | ) internal view returns (uint256, bool, int256) {
1568 | * | GetNextFundingFactorPerSecondCache memory cache;
1569 | |
1570 | * | cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);
1571 | * | cache.totalOpenInterest = longOpenInterest + shortOpenInterest;
1572 | |
1573 | * | if (cache.diffUsd == 0) {
1574 | | return (0, true, 0);
1575 | | }
1576 | |
1577 | * | if (cache.totalOpenInterest == 0) {
1578 | | revert Errors.UnableToGetFundingFactorEmptyOpenInterest();
1579 | | }
1580 | |
1581 | * | cache.fundingExponentFactor = getFundingExponentFactor(
1582 | * | dataStore,
1583 | * | market
1584 | | );
1585 | |
1586 | * | cache.diffUsdAfterExponent = Precision.applyExponentFactor(
1587 | * | cache.diffUsd,
1588 | * | cache.fundingExponentFactor
1589 | | );
1590 | * | cache.diffUsdToOpenInterestFactor = Precision.toFactor(
1591 | * | cache.diffUsdAfterExponent,
1592 | * | cache.totalOpenInterest
1593 | | );
1594 | |
1595 | * | FundingConfigCache memory configCache;
1596 | * | configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(
1597 | * | Keys.fundingIncreaseFactorPerSecondKey(market)
1598 | | );
1599 | |
1600 | * | if (configCache.fundingIncreaseFactorPerSecond == 0) {
1601 | * | cache.fundingFactor = getFundingFactor(dataStore, market);
1602 | * | uint256 maxFundingFactorPerSecond = dataStore.getUint(
1603 | * | Keys.maxFundingFactorPerSecondKey(market)
1604 | | );
1605 | |
1606 | | // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference
1607 | * | uint256 fundingFactorPerSecond = Precision.applyFactor(
1608 | * | cache.diffUsdToOpenInterestFactor,
1609 | * | cache.fundingFactor
1610 | | );
1611 | |
1612 | * | if (fundingFactorPerSecond > maxFundingFactorPerSecond) {
1613 | | fundingFactorPerSecond = maxFundingFactorPerSecond;
1614 | | }
1615 | |
1616 | * | return (
1617 | * | fundingFactorPerSecond,
1618 | * | longOpenInterest > shortOpenInterest,
1619 | * | 0
1620 | | );
1621 | | }
1622 | |
1623 | | // if the savedFundingFactorPerSecond is positive then longs pay shorts
1624 | | // if the savedFundingFactorPerSecond is negative then shorts pay longs
1625 | | cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(
1626 | | dataStore,
1627 | | market
1628 | | );
1629 | | cache.savedFundingFactorPerSecondMagnitude = cache
1630 | | .savedFundingFactorPerSecond
1631 | | .abs();
1632 | |
1633 | | configCache.thresholdForStableFunding = dataStore.getUint(
1634 | | Keys.thresholdForStableFundingKey(market)
1635 | | );
1636 | | configCache.thresholdForDecreaseFunding = dataStore.getUint(
1637 | | Keys.thresholdForDecreaseFundingKey(market)
1638 | | );
1639 | |
1640 | | // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond
1641 | | cache.nextSavedFundingFactorPerSecond = cache
1642 | | .savedFundingFactorPerSecond;
1643 | |
1644 | | // the default will be NoChange
1645 | | FundingRateChangeType fundingRateChangeType;
1646 | |
1647 | | bool isSkewTheSameDirectionAsFunding = (cache
1648 | | .savedFundingFactorPerSecond >
1649 | | 0 &&
1650 | | longOpenInterest > shortOpenInterest) ||
1651 | | (cache.savedFundingFactorPerSecond < 0 &&
1652 | | shortOpenInterest > longOpenInterest);
1653 | |
1654 | | if (isSkewTheSameDirectionAsFunding) {
1655 | | if (
1656 | | cache.diffUsdToOpenInterestFactor >
1657 | | configCache.thresholdForStableFunding
1658 | | ) {
1659 | | fundingRateChangeType = FundingRateChangeType.Increase;
1660 | | } else if (
1661 | | cache.diffUsdToOpenInterestFactor <
1662 | | configCache.thresholdForDecreaseFunding
1663 | | ) {
1664 | | fundingRateChangeType = FundingRateChangeType.Decrease;
1665 | | }
1666 | | } else {
1667 | | // if the skew has changed, then the funding should increase in the opposite direction
1668 | | fundingRateChangeType = FundingRateChangeType.Increase;
1669 | | }
1670 | |
1671 | | if (fundingRateChangeType == FundingRateChangeType.Increase) {
1672 | | // increase funding rate
1673 | | int256 increaseValue = Precision
1674 | | .applyFactor(
1675 | | cache.diffUsdToOpenInterestFactor,
1676 | | configCache.fundingIncreaseFactorPerSecond
1677 | | )
1678 | | .toInt256() * durationInSeconds.toInt256();
1679 | |
1680 | | // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase
1681 | | // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease
1682 | | if (longOpenInterest < shortOpenInterest) {
1683 | | increaseValue = -increaseValue;
1684 | | }
1685 | |
1686 | | cache.nextSavedFundingFactorPerSecond =
1687 | | cache.savedFundingFactorPerSecond +
1688 | | increaseValue;
1689 | | }
1690 | |
1691 | | if (
1692 | | fundingRateChangeType == FundingRateChangeType.Decrease &&
1693 | | cache.savedFundingFactorPerSecondMagnitude != 0
1694 | | ) {
1695 | | configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(
1696 | | Keys.fundingDecreaseFactorPerSecondKey(market)
1697 | | );
1698 | | uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond *
1699 | | durationInSeconds;
1700 | |
1701 | | if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {
1702 | | // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond
1703 | | cache.nextSavedFundingFactorPerSecond =
1704 | | cache.savedFundingFactorPerSecond /
1705 | | cache.savedFundingFactorPerSecondMagnitude.toInt256();
1706 | | } else {
1707 | | // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond
1708 | | int256 sign = cache.savedFundingFactorPerSecond /
1709 | | cache.savedFundingFactorPerSecondMagnitude.toInt256();
1710 | | cache.nextSavedFundingFactorPerSecond =
1711 | | (cache.savedFundingFactorPerSecondMagnitude - decreaseValue)
1712 | | .toInt256() *
1713 | | sign;
1714 | | }
1715 | | }
1716 | |
1717 | | configCache.minFundingFactorPerSecond = dataStore.getUint(
1718 | | Keys.minFundingFactorPerSecondKey(market)
1719 | | );
1720 | | configCache.maxFundingFactorPerSecond = dataStore.getUint(
1721 | | Keys.maxFundingFactorPerSecondKey(market)
1722 | | );
1723 | |
1724 | | cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(
1725 | | cache.nextSavedFundingFactorPerSecond,
1726 | | 0,
1727 | | configCache.maxFundingFactorPerSecond
1728 | | );
1729 | |
1730 | | cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(
1731 | | cache.nextSavedFundingFactorPerSecond,
1732 | | configCache.minFundingFactorPerSecond,
1733 | | configCache.maxFundingFactorPerSecond
1734 | | );
1735 | |
1736 | | return (
1737 | | cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),
1738 | | cache.nextSavedFundingFactorPerSecondWithMinBound > 0,
1739 | | cache.nextSavedFundingFactorPerSecond
1740 | | );
1741 | | }
1742 | |
1743 | | // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size
1744 | * | function getFundingAmountPerSizeDelta(
1745 | | uint256 fundingUsd,
1746 | | uint256 openInterest,
1747 | | uint256 tokenPrice,
1748 | | bool roundUpMagnitude
1749 | * | ) internal pure returns (uint256) {
1750 | * | if (fundingUsd == 0 || openInterest == 0) {
1751 | * | return 0;
1752 | | }
1753 | |
1754 | * | uint256 fundingUsdPerSize = Precision.mulDiv(
1755 | * | fundingUsd,
1756 | * | Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,
1757 | * | openInterest,
1758 | * | roundUpMagnitude
1759 | | );
1760 | |
1761 | * | if (roundUpMagnitude) {
1762 | * | return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);
1763 | | } else {
1764 | * | return fundingUsdPerSize / tokenPrice;
1765 | | }
1766 | | }
1767 | |
1768 | | // @dev update the cumulative borrowing factor for a market
1769 | | // @param dataStore DataStore
1770 | | // @param market the market to update
1771 | | // @param longToken the market's long token
1772 | | // @param shortToken the market's short token
1773 | | // @param prices the prices of the market tokens
1774 | | // @param isLong whether to update the long or short side
1775 | * | function updateCumulativeBorrowingFactor(
1776 | | DataStore dataStore,
1777 | | EventEmitter eventEmitter,
1778 | | Market.Props memory market,
1779 | | MarketPrices memory prices,
1780 | | bool isLong
1781 | * | ) internal {
1782 | * | (
1783 | | ,
1784 | * | /* uint256 nextCumulativeBorrowingFactor */ uint256 delta
1785 | * | ) = getNextCumulativeBorrowingFactor(dataStore, market, prices, isLong);
1786 | |
1787 | * | incrementCumulativeBorrowingFactor(
1788 | * | dataStore,
1789 | * | eventEmitter,
1790 | * | market.marketToken,
1791 | * | isLong,
1792 | * | delta
1793 | | );
1794 | |
1795 | * | dataStore.setUint(
1796 | * | Keys.cumulativeBorrowingFactorUpdatedAtKey(
1797 | * | market.marketToken,
1798 | * | isLong
1799 | | ),
1800 | * | Chain.currentTimestamp()
1801 | | );
1802 | | }
1803 | |
1804 | | // @dev get the ratio of pnl to pool value
1805 | | // @param dataStore DataStore
1806 | | // @param oracle Oracle
1807 | | // @param market the trading market
1808 | | // @param isLong whether to get the value for the long or short side
1809 | | // @param maximize whether to maximize the factor
1810 | | // @return (pnl of positions) / (long or short pool value)
1811 | * | function getPnlToPoolFactor(
1812 | | DataStore dataStore,
1813 | | Oracle oracle,
1814 | | address market,
1815 | | bool isLong,
1816 | | bool maximize
1817 | * | ) internal view returns (int256) {
1818 | * | Market.Props memory _market = getEnabledMarket(dataStore, market);
1819 | * | MarketPrices memory prices = MarketPrices(
1820 | * | oracle.getPrimaryPrice(_market.indexToken),
1821 | * | oracle.getPrimaryPrice(_market.longToken),
1822 | * | oracle.getPrimaryPrice(_market.shortToken)
1823 | | );
1824 | |
1825 | * | return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);
1826 | | }
1827 | |
1828 | | // @dev get the ratio of pnl to pool value
1829 | | // @param dataStore DataStore
1830 | | // @param market the market values
1831 | | // @param prices the prices of the market tokens
1832 | | // @param isLong whether to get the value for the long or short side
1833 | | // @param maximize whether to maximize the factor
1834 | | // @return (pnl of positions) / (long or short pool value)
1835 | * | function getPnlToPoolFactor(
1836 | | DataStore dataStore,
1837 | | Market.Props memory market,
1838 | | MarketPrices memory prices,
1839 | | bool isLong,
1840 | | bool maximize
1841 | * | ) internal view returns (int256) {
1842 | * | uint256 poolUsd = getPoolUsdWithoutPnl(
1843 | * | dataStore,
1844 | * | market,
1845 | * | prices,
1846 | * | isLong,
1847 | * | !maximize
1848 | | );
1849 | |
1850 | * | if (poolUsd == 0) {
1851 | | return 0;
1852 | | }
1853 | |
1854 | * | int256 pnl = getPnl(
1855 | * | dataStore,
1856 | * | market,
1857 | * | prices.indexTokenPrice,
1858 | * | isLong,
1859 | * | maximize
1860 | | );
1861 | |
1862 | * | return Precision.toFactor(pnl, poolUsd);
1863 | | }
1864 | |
1865 | * | function validateOpenInterest(
1866 | | DataStore dataStore,
1867 | | Market.Props memory market,
1868 | | bool isLong
1869 | * | ) internal view {
1870 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
1871 | * | uint256 maxOpenInterest = getMaxOpenInterest(
1872 | * | dataStore,
1873 | * | market.marketToken,
1874 | * | isLong
1875 | | );
1876 | |
1877 | * | if (openInterest > maxOpenInterest) {
1878 | * | revert Errors.MaxOpenInterestExceeded(
1879 | * | openInterest,
1880 | * | maxOpenInterest
1881 | | );
1882 | | }
1883 | | }
1884 | |
1885 | | // @dev validate that the pool amount is within the max allowed amount
1886 | | // @param dataStore DataStore
1887 | | // @param market the market to check
1888 | | // @param token the token to check
1889 | * | function validatePoolAmount(
1890 | | DataStore dataStore,
1891 | | Market.Props memory market,
1892 | | address token
1893 | * | ) internal view {
1894 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token);
1895 | * | uint256 maxPoolAmount = getMaxPoolAmount(
1896 | * | dataStore,
1897 | * | market.marketToken,
1898 | * | token
1899 | | );
1900 | |
1901 | * | if (poolAmount > maxPoolAmount) {
1902 | | revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);
1903 | | }
1904 | | }
1905 | |
1906 | * | function validatePoolUsdForDeposit(
1907 | | DataStore dataStore,
1908 | | Market.Props memory market,
1909 | | address token,
1910 | | uint256 tokenPrice
1911 | * | ) internal view {
1912 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token);
1913 | * | uint256 poolUsd = poolAmount * tokenPrice;
1914 | * | uint256 maxPoolUsd = getMaxPoolUsdForDeposit(
1915 | * | dataStore,
1916 | * | market.marketToken,
1917 | * | token
1918 | | );
1919 | |
1920 | * | if (poolUsd > maxPoolUsd) {
1921 | * | revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);
1922 | | }
1923 | | }
1924 | |
1925 | | // @dev validate that the amount of tokens required to be reserved
1926 | | // is below the configured threshold
1927 | | // @param dataStore DataStore
1928 | | // @param market the market values
1929 | | // @param prices the prices of the market tokens
1930 | | // @param isLong whether to check the long or short side
1931 | * | function validateReserve(
1932 | | DataStore dataStore,
1933 | | Market.Props memory market,
1934 | | MarketPrices memory prices,
1935 | | bool isLong
1936 | * | ) internal view {
1937 | | // poolUsd is used instead of pool amount as the indexToken may not match the longToken
1938 | | // additionally, the shortToken may not be a stablecoin
1939 | * | uint256 poolUsd = getPoolUsdWithoutPnl(
1940 | * | dataStore,
1941 | * | market,
1942 | * | prices,
1943 | * | isLong,
1944 | * | false
1945 | | );
1946 | * | uint256 reserveFactor = getReserveFactor(
1947 | * | dataStore,
1948 | * | market.marketToken,
1949 | * | isLong
1950 | | );
1951 | * | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
1952 | |
1953 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong);
1954 | |
1955 | * | if (reservedUsd > maxReservedUsd) {
1956 | * | revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);
1957 | | }
1958 | | }
1959 | |
1960 | | // @dev validate that the amount of tokens required to be reserved for open interest
1961 | | // is below the configured threshold
1962 | | // @param dataStore DataStore
1963 | | // @param market the market values
1964 | | // @param prices the prices of the market tokens
1965 | | // @param isLong whether to check the long or short side
1966 | * | function validateOpenInterestReserve(
1967 | | DataStore dataStore,
1968 | | Market.Props memory market,
1969 | | MarketPrices memory prices,
1970 | | bool isLong
1971 | * | ) internal view {
1972 | | // poolUsd is used instead of pool amount as the indexToken may not match the longToken
1973 | | // additionally, the shortToken may not be a stablecoin
1974 | * | uint256 poolUsd = getPoolUsdWithoutPnl(
1975 | * | dataStore,
1976 | * | market,
1977 | * | prices,
1978 | * | isLong,
1979 | * | false
1980 | | );
1981 | * | uint256 reserveFactor = getOpenInterestReserveFactor(
1982 | * | dataStore,
1983 | * | market.marketToken,
1984 | * | isLong
1985 | | );
1986 | * | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
1987 | |
1988 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong);
1989 | |
1990 | * | if (reservedUsd > maxReservedUsd) {
1991 | | revert Errors.InsufficientReserveForOpenInterest(
1992 | | reservedUsd,
1993 | | maxReservedUsd
1994 | | );
1995 | | }
1996 | | }
1997 | |
1998 | | // @dev update the swap impact pool amount, if it is a positive impact amount
1999 | | // cap the impact amount to the amount available in the swap impact pool
2000 | | // @param dataStore DataStore
2001 | | // @param eventEmitter EventEmitter
2002 | | // @param market the market to apply to
2003 | | // @param token the token to apply to
2004 | | // @param tokenPrice the price of the token
2005 | | // @param priceImpactUsd the USD price impact
2006 | * | function applySwapImpactWithCap(
2007 | | DataStore dataStore,
2008 | | EventEmitter eventEmitter,
2009 | | address market,
2010 | | address token,
2011 | | Price.Props memory tokenPrice,
2012 | | int256 priceImpactUsd
2013 | * | ) internal returns (int256, uint256) {
2014 | * | (
2015 | * | int256 impactAmount,
2016 | * | uint256 cappedDiffUsd
2017 | * | ) = getSwapImpactAmountWithCap(
2018 | * | dataStore,
2019 | * | market,
2020 | * | token,
2021 | * | tokenPrice,
2022 | * | priceImpactUsd
2023 | | );
2024 | |
2025 | | // if there is a positive impact, the impact pool amount should be reduced
2026 | | // if there is a negative impact, the impact pool amount should be increased
2027 | * | applyDeltaToSwapImpactPool(
2028 | * | dataStore,
2029 | * | eventEmitter,
2030 | * | market,
2031 | * | token,
2032 | * | -impactAmount
2033 | | );
2034 | |
2035 | * | return (impactAmount, cappedDiffUsd);
2036 | | }
2037 | |
2038 | * | function getSwapImpactAmountWithCap(
2039 | | DataStore dataStore,
2040 | | address market,
2041 | | address token,
2042 | | Price.Props memory tokenPrice,
2043 | | int256 priceImpactUsd
2044 | * | ) internal view returns (int256, uint256) {
2045 | * | int256 impactAmount;
2046 | * | uint256 cappedDiffUsd;
2047 | |
2048 | * | if (priceImpactUsd > 0) {
2049 | | // positive impact: minimize impactAmount, use tokenPrice.max
2050 | | // round positive impactAmount down, this will be deducted from the swap impact pool for the user
2051 | | impactAmount = priceImpactUsd / tokenPrice.max.toInt256();
2052 | |
2053 | | int256 maxImpactAmount = getSwapImpactPoolAmount(
2054 | | dataStore,
2055 | | market,
2056 | | token
2057 | | ).toInt256();
2058 | | if (impactAmount > maxImpactAmount) {
2059 | | cappedDiffUsd =
2060 | | (impactAmount - maxImpactAmount).toUint256() *
2061 | | tokenPrice.max;
2062 | | impactAmount = maxImpactAmount;
2063 | | }
2064 | | } else {
2065 | | // negative impact: maximize impactAmount, use tokenPrice.min
2066 | | // round negative impactAmount up, this will be deducted from the user
2067 | * | impactAmount = Calc.roundUpMagnitudeDivision(
2068 | * | priceImpactUsd,
2069 | * | tokenPrice.min
2070 | | );
2071 | | }
2072 | |
2073 | * | return (impactAmount, cappedDiffUsd);
2074 | | }
2075 | |
2076 | | // @dev get the funding amount to be deducted or distributed
2077 | | //
2078 | | // @param latestFundingAmountPerSize the latest funding amount per size
2079 | | // @param positionFundingAmountPerSize the funding amount per size for the position
2080 | | // @param positionSizeInUsd the position size in USD
2081 | | // @param roundUpMagnitude whether the round up the result
2082 | | //
2083 | | // @return fundingAmount
2084 | * | function getFundingAmount(
2085 | | uint256 latestFundingAmountPerSize,
2086 | | uint256 positionFundingAmountPerSize,
2087 | | uint256 positionSizeInUsd,
2088 | | bool roundUpMagnitude
2089 | * | ) internal pure returns (uint256) {
2090 | * | uint256 fundingDiffFactor = (latestFundingAmountPerSize -
2091 | * | positionFundingAmountPerSize);
2092 | |
2093 | | // a user could avoid paying funding fees by continually updating the position
2094 | | // before the funding fee becomes large enough to be chargeable
2095 | | // to avoid this, funding fee amounts should be rounded up
2096 | | //
2097 | | // this could lead to large additional charges if the token has a low number of decimals
2098 | | // or if the token's value is very high, so care should be taken to inform users of this
2099 | | //
2100 | | // if the calculation is for the claimable amount, the amount should be rounded down instead
2101 | |
2102 | | // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values
2103 | | // are stored based on FLOAT_PRECISION_SQRT values
2104 | * | return
2105 | * | Precision.mulDiv(
2106 | * | positionSizeInUsd,
2107 | * | fundingDiffFactor,
2108 | * | Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,
2109 | * | roundUpMagnitude
2110 | | );
2111 | | }
2112 | |
2113 | | // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor
2114 | | // has already been updated to the latest value
2115 | | // @param dataStore DataStore
2116 | | // @param position Position.Props
2117 | | // @return the borrowing fees for a position
2118 | * | function getBorrowingFees(
2119 | | DataStore dataStore,
2120 | | Position.Props memory position
2121 | * | ) internal view returns (uint256) {
2122 | * | uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(
2123 | * | dataStore,
2124 | * | position.market(),
2125 | * | position.isLong()
2126 | | );
2127 | * | if (position.borrowingFactor() > cumulativeBorrowingFactor) {
2128 | | revert Errors.UnexpectedBorrowingFactor(
2129 | | position.borrowingFactor(),
2130 | | cumulativeBorrowingFactor
2131 | | );
2132 | | }
2133 | * | uint256 diffFactor = cumulativeBorrowingFactor -
2134 | * | position.borrowingFactor();
2135 | * | return Precision.applyFactor(position.sizeInUsd(), diffFactor);
2136 | | }
2137 | |
2138 | | // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor
2139 | | // @param dataStore DataStore
2140 | | // @param position Position.Props
2141 | | // @param market the position's market
2142 | | // @param prices the prices of the market tokens
2143 | | // @return the borrowing fees for a position
2144 | * | function getNextBorrowingFees(
2145 | | DataStore dataStore,
2146 | | Position.Props memory position,
2147 | | Market.Props memory market,
2148 | | MarketPrices memory prices
2149 | * | ) internal view returns (uint256) {
2150 | * | (
2151 | * | uint256 nextCumulativeBorrowingFactor /* uint256 delta */,
2152 | |
2153 | * | ) = getNextCumulativeBorrowingFactor(
2154 | * | dataStore,
2155 | * | market,
2156 | * | prices,
2157 | * | position.isLong()
2158 | | );
2159 | |
2160 | * | if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {
2161 | | revert Errors.UnexpectedBorrowingFactor(
2162 | | position.borrowingFactor(),
2163 | | nextCumulativeBorrowingFactor
2164 | | );
2165 | | }
2166 | * | uint256 diffFactor = nextCumulativeBorrowingFactor -
2167 | * | position.borrowingFactor();
2168 | * | return Precision.applyFactor(position.sizeInUsd(), diffFactor);
2169 | | }
2170 | |
2171 | | // @dev get the total reserved USD required for positions
2172 | | // @param market the market to check
2173 | | // @param prices the prices of the market tokens
2174 | | // @param isLong whether to get the value for the long or short side
2175 | * | function getReservedUsd(
2176 | | DataStore dataStore,
2177 | | Market.Props memory market,
2178 | | MarketPrices memory prices,
2179 | | bool isLong
2180 | * | ) internal view returns (uint256) {
2181 | * | uint256 reservedUsd;
2182 | * | if (isLong) {
2183 | | // for longs calculate the reserved USD based on the open interest and current indexTokenPrice
2184 | | // this works well for e.g. an ETH / USD market with long collateral token as WETH
2185 | | // the available amount to be reserved would scale with the price of ETH
2186 | | // this also works for e.g. a SOL / USD market with long collateral token as WETH
2187 | | // if the price of SOL increases more than the price of ETH, additional amounts would be
2188 | | // automatically reserved
2189 | * | uint256 openInterestInTokens = getOpenInterestInTokens(
2190 | * | dataStore,
2191 | * | market,
2192 | * | isLong
2193 | | );
2194 | * | reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;
2195 | | } else {
2196 | | // for shorts use the open interest as the reserved USD value
2197 | | // this works well for e.g. an ETH / USD market with short collateral token as USDC
2198 | | // the available amount to be reserved would not change with the price of ETH
2199 | * | reservedUsd = getOpenInterest(dataStore, market, isLong);
2200 | | }
2201 | |
2202 | * | return reservedUsd;
2203 | | }
2204 | |
2205 | | // @dev get the virtual inventory for swaps
2206 | | // @param dataStore DataStore
2207 | | // @param market the market to check
2208 | | // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory)
2209 | * | function getVirtualInventoryForSwaps(
2210 | | DataStore dataStore,
2211 | | address market
2212 | * | ) internal view returns (bool, uint256, uint256) {
2213 | * | bytes32 virtualMarketId = dataStore.getBytes32(
2214 | * | Keys.virtualMarketIdKey(market)
2215 | | );
2216 | * | if (virtualMarketId == bytes32(0)) {
2217 | * | return (false, 0, 0);
2218 | | }
2219 | |
2220 | | return (
2221 | | true,
2222 | | dataStore.getUint(
2223 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, true)
2224 | | ),
2225 | | dataStore.getUint(
2226 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, false)
2227 | | )
2228 | | );
2229 | | }
2230 | |
2231 | | function getIsLongToken(
2232 | | Market.Props memory market,
2233 | | address token
2234 | | ) internal pure returns (bool) {
2235 | | if (token != market.longToken && token != market.shortToken) {
2236 | | revert Errors.UnexpectedTokenForVirtualInventory(
2237 | | token,
2238 | | market.marketToken
2239 | | );
2240 | | }
2241 | |
2242 | | return token == market.longToken;
2243 | | }
2244 | |
2245 | | // @dev get the virtual inventory for positions
2246 | | // @param dataStore DataStore
2247 | | // @param token the token to check
2248 | * | function getVirtualInventoryForPositions(
2249 | | DataStore dataStore,
2250 | | address token
2251 | * | ) internal view returns (bool, int256) {
2252 | * | bytes32 virtualTokenId = dataStore.getBytes32(
2253 | * | Keys.virtualTokenIdKey(token)
2254 | | );
2255 | * | if (virtualTokenId == bytes32(0)) {
2256 | * | return (false, 0);
2257 | | }
2258 | |
2259 | | return (
2260 | | true,
2261 | | dataStore.getInt(
2262 | | Keys.virtualInventoryForPositionsKey(virtualTokenId)
2263 | | )
2264 | | );
2265 | | }
2266 | |
2267 | | // @dev update the virtual inventory for swaps
2268 | | // @param dataStore DataStore
2269 | | // @param marketAddress the market to update
2270 | | // @param token the token to update
2271 | | // @param delta the update amount
2272 | * | function applyDeltaToVirtualInventoryForSwaps(
2273 | | DataStore dataStore,
2274 | | EventEmitter eventEmitter,
2275 | | Market.Props memory market,
2276 | | address token,
2277 | | int256 delta
2278 | * | ) internal returns (bool, uint256) {
2279 | * | bytes32 virtualMarketId = dataStore.getBytes32(
2280 | * | Keys.virtualMarketIdKey(market.marketToken)
2281 | | );
2282 | * | if (virtualMarketId == bytes32(0)) {
2283 | * | return (false, 0);
2284 | | }
2285 | |
2286 | | bool isLongToken = getIsLongToken(market, token);
2287 | |
2288 | | uint256 nextValue = dataStore.applyBoundedDeltaToUint(
2289 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),
2290 | | delta
2291 | | );
2292 | |
2293 | | MarketEventUtils.emitVirtualSwapInventoryUpdated(
2294 | | eventEmitter,
2295 | | market.marketToken,
2296 | | isLongToken,
2297 | | virtualMarketId,
2298 | | delta,
2299 | | nextValue
2300 | | );
2301 | |
2302 | | return (true, nextValue);
2303 | | }
2304 | |
2305 | | // @dev update the virtual inventory for positions
2306 | | // @param dataStore DataStore
2307 | | // @param eventEmitter EventEmitter
2308 | | // @param token the token to update
2309 | | // @param delta the update amount
2310 | * | function applyDeltaToVirtualInventoryForPositions(
2311 | | DataStore dataStore,
2312 | | EventEmitter eventEmitter,
2313 | | address token,
2314 | | int256 delta
2315 | * | ) internal returns (bool, int256) {
2316 | * | bytes32 virtualTokenId = dataStore.getBytes32(
2317 | * | Keys.virtualTokenIdKey(token)
2318 | | );
2319 | * | if (virtualTokenId == bytes32(0)) {
2320 | * | return (false, 0);
2321 | | }
2322 | |
2323 | | int256 nextValue = dataStore.applyDeltaToInt(
2324 | | Keys.virtualInventoryForPositionsKey(virtualTokenId),
2325 | | delta
2326 | | );
2327 | |
2328 | | MarketEventUtils.emitVirtualPositionInventoryUpdated(
2329 | | eventEmitter,
2330 | | token,
2331 | | virtualTokenId,
2332 | | delta,
2333 | | nextValue
2334 | | );
2335 | |
2336 | | return (true, nextValue);
2337 | | }
2338 | |
2339 | | // @dev get the open interest of a market
2340 | | // @param dataStore DataStore
2341 | | // @param market the market to check
2342 | | // @param longToken the long token of the market
2343 | | // @param shortToken the short token of the market
2344 | | function getOpenInterest(
2345 | | DataStore dataStore,
2346 | | Market.Props memory market
2347 | | ) internal view returns (uint256) {
2348 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true);
2349 | | uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);
2350 | |
2351 | | return longOpenInterest + shortOpenInterest;
2352 | | }
2353 | |
2354 | | // @dev get either the long or short open interest for a market
2355 | | // @param dataStore DataStore
2356 | | // @param market the market to check
2357 | | // @param longToken the long token of the market
2358 | | // @param shortToken the short token of the market
2359 | | // @param isLong whether to get the long or short open interest
2360 | | // @return the long or short open interest for a market
2361 | * | function getOpenInterest(
2362 | | DataStore dataStore,
2363 | | Market.Props memory market,
2364 | | bool isLong
2365 | * | ) internal view returns (uint256) {
2366 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
2367 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(
2368 | * | dataStore,
2369 | * | market.marketToken,
2370 | * | market.longToken,
2371 | * | isLong,
2372 | * | divisor
2373 | | );
2374 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(
2375 | * | dataStore,
2376 | * | market.marketToken,
2377 | * | market.shortToken,
2378 | * | isLong,
2379 | * | divisor
2380 | | );
2381 | |
2382 | * | return
2383 | * | openInterestUsingLongTokenAsCollateral +
2384 | * | openInterestUsingShortTokenAsCollateral;
2385 | | }
2386 | |
2387 | | // @dev the long and short open interest for a market based on the collateral token used
2388 | | // @param dataStore DataStore
2389 | | // @param market the market to check
2390 | | // @param collateralToken the collateral token to check
2391 | | // @param isLong whether to check the long or short side
2392 | * | function getOpenInterest(
2393 | | DataStore dataStore,
2394 | | address market,
2395 | | address collateralToken,
2396 | | bool isLong,
2397 | | uint256 divisor
2398 | * | ) internal view returns (uint256) {
2399 | * | return
2400 | * | dataStore.getUint(
2401 | * | Keys.openInterestKey(market, collateralToken, isLong)
2402 | * | ) / divisor;
2403 | | }
2404 | |
2405 | | // this is used to divide the values of getPoolAmount and getOpenInterest
2406 | | // if the longToken and shortToken are the same, then these values have to be divided by two
2407 | | // to avoid double counting
2408 | * | function getPoolDivisor(
2409 | | address longToken,
2410 | | address shortToken
2411 | * | ) internal pure returns (uint256) {
2412 | * | return longToken == shortToken ? 2 : 1;
2413 | | }
2414 | |
2415 | | // @dev the long and short open interest in tokens for a market
2416 | | // @param dataStore DataStore
2417 | | // @param market the market to check
2418 | | // @param longToken the long token of the market
2419 | | // @param shortToken the short token of the market
2420 | | // @param isLong whether to check the long or short side
2421 | * | function getOpenInterestInTokens(
2422 | | DataStore dataStore,
2423 | | Market.Props memory market,
2424 | | bool isLong
2425 | * | ) internal view returns (uint256) {
2426 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
2427 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(
2428 | * | dataStore,
2429 | * | market.marketToken,
2430 | * | market.longToken,
2431 | * | isLong,
2432 | * | divisor
2433 | | );
2434 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(
2435 | * | dataStore,
2436 | * | market.marketToken,
2437 | * | market.shortToken,
2438 | * | isLong,
2439 | * | divisor
2440 | | );
2441 | |
2442 | * | return
2443 | * | openInterestUsingLongTokenAsCollateral +
2444 | * | openInterestUsingShortTokenAsCollateral;
2445 | | }
2446 | |
2447 | | // @dev the long and short open interest in tokens for a market based on the collateral token used
2448 | | // @param dataStore DataStore
2449 | | // @param market the market to check
2450 | | // @param collateralToken the collateral token to check
2451 | | // @param isLong whether to check the long or short side
2452 | * | function getOpenInterestInTokens(
2453 | | DataStore dataStore,
2454 | | address market,
2455 | | address collateralToken,
2456 | | bool isLong,
2457 | | uint256 divisor
2458 | * | ) internal view returns (uint256) {
2459 | * | return
2460 | * | dataStore.getUint(
2461 | * | Keys.openInterestInTokensKey(market, collateralToken, isLong)
2462 | * | ) / divisor;
2463 | | }
2464 | |
2465 | | // @dev get the sum of open interest and pnl for a market
2466 | | // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl
2467 | | // for short positions, so getOpenInterestWithPnl should be used if that info is needed
2468 | | // @param dataStore DataStore
2469 | | // @param market the market to check
2470 | | // @param longToken the long token of the market
2471 | | // @param shortToken the short token of the market
2472 | | // @param indexTokenPrice the price of the index token
2473 | | // @param isLong whether to check the long or short side
2474 | | // @param maximize whether to maximize or minimize the value
2475 | | // @return the sum of open interest and pnl for a market
2476 | | function getOpenInterestWithPnl(
2477 | | DataStore dataStore,
2478 | | Market.Props memory market,
2479 | | Price.Props memory indexTokenPrice,
2480 | | bool isLong,
2481 | | bool maximize
2482 | | ) internal view returns (int256) {
2483 | | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
2484 | | int256 pnl = getPnl(
2485 | | dataStore,
2486 | | market,
2487 | | indexTokenPrice,
2488 | | isLong,
2489 | | maximize
2490 | | );
2491 | | return Calc.sumReturnInt256(openInterest, pnl);
2492 | | }
2493 | |
2494 | | // @dev get the max position impact factor for decreasing position
2495 | | // @param dataStore DataStore
2496 | | // @param market the market to check
2497 | | // @param isPositive whether the price impact is positive or negative
2498 | * | function getMaxPositionImpactFactor(
2499 | | DataStore dataStore,
2500 | | address market,
2501 | | bool isPositive
2502 | * | ) internal view returns (uint256) {
2503 | * | (
2504 | * | uint256 maxPositiveImpactFactor,
2505 | * | uint256 maxNegativeImpactFactor
2506 | * | ) = getMaxPositionImpactFactors(dataStore, market);
2507 | |
2508 | * | return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;
2509 | | }
2510 | |
2511 | * | function getMaxPositionImpactFactors(
2512 | | DataStore dataStore,
2513 | | address market
2514 | * | ) internal view returns (uint256, uint256) {
2515 | * | uint256 maxPositiveImpactFactor = dataStore.getUint(
2516 | * | Keys.maxPositionImpactFactorKey(market, true)
2517 | | );
2518 | * | uint256 maxNegativeImpactFactor = dataStore.getUint(
2519 | * | Keys.maxPositionImpactFactorKey(market, false)
2520 | | );
2521 | |
2522 | * | if (maxPositiveImpactFactor > maxNegativeImpactFactor) {
2523 | | maxPositiveImpactFactor = maxNegativeImpactFactor;
2524 | | }
2525 | |
2526 | * | return (maxPositiveImpactFactor, maxNegativeImpactFactor);
2527 | | }
2528 | |
2529 | | // @dev get the max position impact factor for liquidations
2530 | | // @param dataStore DataStore
2531 | | // @param market the market to check
2532 | | function getMaxPositionImpactFactorForLiquidations(
2533 | | DataStore dataStore,
2534 | | address market
2535 | | ) internal view returns (uint256) {
2536 | | return
2537 | | dataStore.getUint(
2538 | | Keys.maxPositionImpactFactorForLiquidationsKey(market)
2539 | | );
2540 | | }
2541 | |
2542 | | // @dev get the min collateral factor
2543 | | // @param dataStore DataStore
2544 | | // @param market the market to check
2545 | * | function getMinCollateralFactor(
2546 | | DataStore dataStore,
2547 | | address market
2548 | * | ) internal view returns (uint256) {
2549 | * | return dataStore.getUint(Keys.minCollateralFactorKey(market));
2550 | | }
2551 | |
2552 | | // @dev get the min collateral factor for open interest multiplier
2553 | | // @param dataStore DataStore
2554 | | // @param market the market to check
2555 | | // @param isLong whether it is for the long or short side
2556 | * | function getMinCollateralFactorForOpenInterestMultiplier(
2557 | | DataStore dataStore,
2558 | | address market,
2559 | | bool isLong
2560 | * | ) internal view returns (uint256) {
2561 | * | return
2562 | * | dataStore.getUint(
2563 | * | Keys.minCollateralFactorForOpenInterestMultiplierKey(
2564 | * | market,
2565 | * | isLong
2566 | | )
2567 | | );
2568 | | }
2569 | |
2570 | | // @dev get the min collateral factor for open interest
2571 | | // @param dataStore DataStore
2572 | | // @param market the market to check
2573 | | // @param longToken the long token of the market
2574 | | // @param shortToken the short token of the market
2575 | | // @param openInterestDelta the change in open interest
2576 | | // @param isLong whether it is for the long or short side
2577 | * | function getMinCollateralFactorForOpenInterest(
2578 | | DataStore dataStore,
2579 | | Market.Props memory market,
2580 | | int256 openInterestDelta,
2581 | | bool isLong
2582 | * | ) internal view returns (uint256) {
2583 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
2584 | * | openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);
2585 | * | uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(
2586 | * | dataStore,
2587 | * | market.marketToken,
2588 | * | isLong
2589 | | );
2590 | * | return Precision.applyFactor(openInterest, multiplierFactor);
2591 | | }
2592 | |
2593 | | // @dev get the total amount of position collateral for a market
2594 | | // @param dataStore DataStore
2595 | | // @param market the market to check
2596 | | // @param collateralToken the collateralToken to check
2597 | | // @param isLong whether to get the value for longs or shorts
2598 | | // @return the total amount of position collateral for a market
2599 | * | function getCollateralSum(
2600 | | DataStore dataStore,
2601 | | address market,
2602 | | address collateralToken,
2603 | | bool isLong,
2604 | | uint256 divisor
2605 | * | ) internal view returns (uint256) {
2606 | * | return
2607 | * | dataStore.getUint(
2608 | * | Keys.collateralSumKey(market, collateralToken, isLong)
2609 | * | ) / divisor;
2610 | | }
2611 | |
2612 | | // @dev get the reserve factor for a market
2613 | | // @param dataStore DataStore
2614 | | // @param market the market to check
2615 | | // @param isLong whether to get the value for longs or shorts
2616 | | // @return the reserve factor for a market
2617 | * | function getReserveFactor(
2618 | | DataStore dataStore,
2619 | | address market,
2620 | | bool isLong
2621 | * | ) internal view returns (uint256) {
2622 | * | return dataStore.getUint(Keys.reserveFactorKey(market, isLong));
2623 | | }
2624 | |
2625 | | // @dev get the open interest reserve factor for a market
2626 | | // @param dataStore DataStore
2627 | | // @param market the market to check
2628 | | // @param isLong whether to get the value for longs or shorts
2629 | | // @return the open interest reserve factor for a market
2630 | * | function getOpenInterestReserveFactor(
2631 | | DataStore dataStore,
2632 | | address market,
2633 | | bool isLong
2634 | * | ) internal view returns (uint256) {
2635 | * | return
2636 | * | dataStore.getUint(
2637 | * | Keys.openInterestReserveFactorKey(market, isLong)
2638 | | );
2639 | | }
2640 | |
2641 | | // @dev get the max pnl factor for a market
2642 | | // @param dataStore DataStore
2643 | | // @param pnlFactorType the type of the pnl factor
2644 | | // @param market the market to check
2645 | | // @param isLong whether to get the value for longs or shorts
2646 | | // @return the max pnl factor for a market
2647 | * | function getMaxPnlFactor(
2648 | | DataStore dataStore,
2649 | | bytes32 pnlFactorType,
2650 | | address market,
2651 | | bool isLong
2652 | * | ) internal view returns (uint256) {
2653 | * | return
2654 | * | dataStore.getUint(
2655 | * | Keys.maxPnlFactorKey(pnlFactorType, market, isLong)
2656 | | );
2657 | | }
2658 | |
2659 | | // @dev get the min pnl factor after ADL
2660 | | // @param dataStore DataStore
2661 | | // @param market the market to check
2662 | | // @param isLong whether to check the long or short side
2663 | * | function getMinPnlFactorAfterAdl(
2664 | | DataStore dataStore,
2665 | | address market,
2666 | | bool isLong
2667 | * | ) internal view returns (uint256) {
2668 | * | return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));
2669 | | }
2670 | |
2671 | | // @dev get the funding factor for a market
2672 | | // @param dataStore DataStore
2673 | | // @param market the market to check
2674 | | // @return the funding factor for a market
2675 | * | function getFundingFactor(
2676 | | DataStore dataStore,
2677 | | address market
2678 | * | ) internal view returns (uint256) {
2679 | * | return dataStore.getUint(Keys.fundingFactorKey(market));
2680 | | }
2681 | |
2682 | | // @dev get the saved funding factor for a market
2683 | | // @param dataStore DataStore
2684 | | // @param market the market to check
2685 | | // @return the saved funding factor for a market
2686 | | function getSavedFundingFactorPerSecond(
2687 | | DataStore dataStore,
2688 | | address market
2689 | | ) internal view returns (int256) {
2690 | | return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));
2691 | | }
2692 | |
2693 | | // @dev set the saved funding factor
2694 | | // @param dataStore DataStore
2695 | | // @param market the market to set the funding factor for
2696 | * | function setSavedFundingFactorPerSecond(
2697 | | DataStore dataStore,
2698 | | address market,
2699 | | int256 value
2700 | * | ) internal returns (int256) {
2701 | * | return
2702 | * | dataStore.setInt(
2703 | * | Keys.savedFundingFactorPerSecondKey(market),
2704 | * | value
2705 | | );
2706 | | }
2707 | |
2708 | | // @dev get the funding exponent factor for a market
2709 | | // @param dataStore DataStore
2710 | | // @param market the market to check
2711 | | // @return the funding exponent factor for a market
2712 | * | function getFundingExponentFactor(
2713 | | DataStore dataStore,
2714 | | address market
2715 | * | ) internal view returns (uint256) {
2716 | * | return dataStore.getUint(Keys.fundingExponentFactorKey(market));
2717 | | }
2718 | |
2719 | | // @dev get the funding fee amount per size for a market
2720 | | // @param dataStore DataStore
2721 | | // @param market the market to check
2722 | | // @param collateralToken the collateralToken to check
2723 | | // @param isLong whether to check the long or short size
2724 | | // @return the funding fee amount per size for a market based on collateralToken
2725 | * | function getFundingFeeAmountPerSize(
2726 | | DataStore dataStore,
2727 | | address market,
2728 | | address collateralToken,
2729 | | bool isLong
2730 | * | ) internal view returns (uint256) {
2731 | * | return
2732 | * | dataStore.getUint(
2733 | * | Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong)
2734 | | );
2735 | | }
2736 | |
2737 | | // @dev get the claimable funding amount per size for a market
2738 | | // @param dataStore DataStore
2739 | | // @param market the market to check
2740 | | // @param collateralToken the collateralToken to check
2741 | | // @param isLong whether to check the long or short size
2742 | | // @return the claimable funding amount per size for a market based on collateralToken
2743 | * | function getClaimableFundingAmountPerSize(
2744 | | DataStore dataStore,
2745 | | address market,
2746 | | address collateralToken,
2747 | | bool isLong
2748 | * | ) internal view returns (uint256) {
2749 | * | return
2750 | * | dataStore.getUint(
2751 | * | Keys.claimableFundingAmountPerSizeKey(
2752 | * | market,
2753 | * | collateralToken,
2754 | * | isLong
2755 | | )
2756 | | );
2757 | | }
2758 | |
2759 | | // @dev apply delta to the funding fee amount per size for a market
2760 | | // @param dataStore DataStore
2761 | | // @param market the market to set
2762 | | // @param collateralToken the collateralToken to set
2763 | | // @param isLong whether to set it for the long or short side
2764 | | // @param delta the delta to increment by
2765 | * | function applyDeltaToFundingFeeAmountPerSize(
2766 | | DataStore dataStore,
2767 | | EventEmitter eventEmitter,
2768 | | address market,
2769 | | address collateralToken,
2770 | | bool isLong,
2771 | | uint256 delta
2772 | * | ) internal {
2773 | * | if (delta == 0) {
2774 | * | return;
2775 | | }
2776 | |
2777 | * | uint256 nextValue = dataStore.applyDeltaToUint(
2778 | * | Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),
2779 | * | delta
2780 | | );
2781 | |
2782 | * | MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(
2783 | * | eventEmitter,
2784 | * | market,
2785 | * | collateralToken,
2786 | * | isLong,
2787 | * | delta,
2788 | * | nextValue
2789 | | );
2790 | | }
2791 | |
2792 | | // @dev apply delta to the claimable funding amount per size for a market
2793 | | // @param dataStore DataStore
2794 | | // @param market the market to set
2795 | | // @param collateralToken the collateralToken to set
2796 | | // @param isLong whether to set it for the long or short side
2797 | | // @param delta the delta to increment by
2798 | * | function applyDeltaToClaimableFundingAmountPerSize(
2799 | | DataStore dataStore,
2800 | | EventEmitter eventEmitter,
2801 | | address market,
2802 | | address collateralToken,
2803 | | bool isLong,
2804 | | uint256 delta
2805 | * | ) internal {
2806 | * | if (delta == 0) {
2807 | * | return;
2808 | | }
2809 | |
2810 | * | uint256 nextValue = dataStore.applyDeltaToUint(
2811 | * | Keys.claimableFundingAmountPerSizeKey(
2812 | * | market,
2813 | * | collateralToken,
2814 | * | isLong
2815 | | ),
2816 | * | delta
2817 | | );
2818 | |
2819 | * | MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(
2820 | * | eventEmitter,
2821 | * | market,
2822 | * | collateralToken,
2823 | * | isLong,
2824 | * | delta,
2825 | * | nextValue
2826 | | );
2827 | | }
2828 | |
2829 | | // @dev get the number of seconds since funding was updated for a market
2830 | | // @param market the market to check
2831 | | // @return the number of seconds since funding was updated for a market
2832 | * | function getSecondsSinceFundingUpdated(
2833 | | DataStore dataStore,
2834 | | address market
2835 | * | ) internal view returns (uint256) {
2836 | * | uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));
2837 | * | if (updatedAt == 0) {
2838 | | return 0;
2839 | | }
2840 | * | return Chain.currentTimestamp() - updatedAt;
2841 | | }
2842 | |
2843 | | // @dev get the borrowing factor for a market
2844 | | // @param dataStore DataStore
2845 | | // @param market the market to check
2846 | | // @param isLong whether to check the long or short side
2847 | | // @return the borrowing factor for a market
2848 | * | function getBorrowingFactor(
2849 | | DataStore dataStore,
2850 | | address market,
2851 | | bool isLong
2852 | * | ) internal view returns (uint256) {
2853 | * | return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));
2854 | | }
2855 | |
2856 | * | function getOptimalUsageFactor(
2857 | | DataStore dataStore,
2858 | | address market,
2859 | | bool isLong
2860 | * | ) internal view returns (uint256) {
2861 | * | return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));
2862 | | }
2863 | |
2864 | | // @dev get the borrowing exponent factor for a market
2865 | | // @param dataStore DataStore
2866 | | // @param market the market to check
2867 | | // @param isLong whether to check the long or short side
2868 | | // @return the borrowing exponent factor for a market
2869 | * | function getBorrowingExponentFactor(
2870 | | DataStore dataStore,
2871 | | address market,
2872 | | bool isLong
2873 | * | ) internal view returns (uint256) {
2874 | * | return
2875 | * | dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));
2876 | | }
2877 | |
2878 | | // @dev get the cumulative borrowing factor for a market
2879 | | // @param dataStore DataStore
2880 | | // @param market the market to check
2881 | | // @param isLong whether to check the long or short side
2882 | | // @return the cumulative borrowing factor for a market
2883 | * | function getCumulativeBorrowingFactor(
2884 | | DataStore dataStore,
2885 | | address market,
2886 | | bool isLong
2887 | * | ) internal view returns (uint256) {
2888 | * | return
2889 | * | dataStore.getUint(
2890 | * | Keys.cumulativeBorrowingFactorKey(market, isLong)
2891 | | );
2892 | | }
2893 | |
2894 | | // @dev increase the cumulative borrowing factor
2895 | | // @param dataStore DataStore
2896 | | // @param eventEmitter EventEmitter
2897 | | // @param market the market to increment the borrowing factor for
2898 | | // @param isLong whether to increment the long or short side
2899 | | // @param delta the increase amount
2900 | * | function incrementCumulativeBorrowingFactor(
2901 | | DataStore dataStore,
2902 | | EventEmitter eventEmitter,
2903 | | address market,
2904 | | bool isLong,
2905 | | uint256 delta
2906 | * | ) internal {
2907 | * | uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(
2908 | * | Keys.cumulativeBorrowingFactorKey(market, isLong),
2909 | * | delta
2910 | | );
2911 | |
2912 | * | MarketEventUtils.emitBorrowingFactorUpdated(
2913 | * | eventEmitter,
2914 | * | market,
2915 | * | isLong,
2916 | * | delta,
2917 | * | nextCumulativeBorrowingFactor
2918 | | );
2919 | | }
2920 | |
2921 | | // @dev get the timestamp of when the cumulative borrowing factor was last updated
2922 | | // @param dataStore DataStore
2923 | | // @param market the market to check
2924 | | // @param isLong whether to check the long or short side
2925 | | // @return the timestamp of when the cumulative borrowing factor was last updated
2926 | * | function getCumulativeBorrowingFactorUpdatedAt(
2927 | | DataStore dataStore,
2928 | | address market,
2929 | | bool isLong
2930 | * | ) internal view returns (uint256) {
2931 | * | return
2932 | * | dataStore.getUint(
2933 | * | Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong)
2934 | | );
2935 | | }
2936 | |
2937 | | // @dev get the number of seconds since the cumulative borrowing factor was last updated
2938 | | // @param dataStore DataStore
2939 | | // @param market the market to check
2940 | | // @param isLong whether to check the long or short side
2941 | | // @return the number of seconds since the cumulative borrowing factor was last updated
2942 | * | function getSecondsSinceCumulativeBorrowingFactorUpdated(
2943 | | DataStore dataStore,
2944 | | address market,
2945 | | bool isLong
2946 | * | ) internal view returns (uint256) {
2947 | * | uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(
2948 | * | dataStore,
2949 | * | market,
2950 | * | isLong
2951 | | );
2952 | * | if (updatedAt == 0) {
2953 | * | return 0;
2954 | | }
2955 | * | return Chain.currentTimestamp() - updatedAt;
2956 | | }
2957 | |
2958 | | // @dev update the total borrowing amount after a position changes size
2959 | | // this is the sum of all position.borrowingFactor * position.sizeInUsd
2960 | | // @param dataStore DataStore
2961 | | // @param market the market to update
2962 | | // @param isLong whether to update the long or short side
2963 | | // @param prevPositionSizeInUsd the previous position size in USD
2964 | | // @param prevPositionBorrowingFactor the previous position borrowing factor
2965 | | // @param nextPositionSizeInUsd the next position size in USD
2966 | | // @param nextPositionBorrowingFactor the next position borrowing factor
2967 | * | function updateTotalBorrowing(
2968 | | DataStore dataStore,
2969 | | address market,
2970 | | bool isLong,
2971 | | uint256 prevPositionSizeInUsd,
2972 | | uint256 prevPositionBorrowingFactor,
2973 | | uint256 nextPositionSizeInUsd,
2974 | | uint256 nextPositionBorrowingFactor
2975 | * | ) internal {
2976 | * | uint256 totalBorrowing = getNextTotalBorrowing(
2977 | * | dataStore,
2978 | * | market,
2979 | * | isLong,
2980 | * | prevPositionSizeInUsd,
2981 | * | prevPositionBorrowingFactor,
2982 | * | nextPositionSizeInUsd,
2983 | * | nextPositionBorrowingFactor
2984 | | );
2985 | |
2986 | * | setTotalBorrowing(dataStore, market, isLong, totalBorrowing);
2987 | | }
2988 | |
2989 | | // @dev get the next total borrowing amount after a position changes size
2990 | | // @param dataStore DataStore
2991 | | // @param market the market to check
2992 | | // @param isLong whether to check the long or short side
2993 | | // @param prevPositionSizeInUsd the previous position size in USD
2994 | | // @param prevPositionBorrowingFactor the previous position borrowing factor
2995 | | // @param nextPositionSizeInUsd the next position size in USD
2996 | | // @param nextPositionBorrowingFactor the next position borrowing factor
2997 | * | function getNextTotalBorrowing(
2998 | | DataStore dataStore,
2999 | | address market,
3000 | | bool isLong,
3001 | | uint256 prevPositionSizeInUsd,
3002 | | uint256 prevPositionBorrowingFactor,
3003 | | uint256 nextPositionSizeInUsd,
3004 | | uint256 nextPositionBorrowingFactor
3005 | * | ) internal view returns (uint256) {
3006 | * | uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);
3007 | * | totalBorrowing -= Precision.applyFactor(
3008 | * | prevPositionSizeInUsd,
3009 | * | prevPositionBorrowingFactor
3010 | | );
3011 | * | totalBorrowing += Precision.applyFactor(
3012 | * | nextPositionSizeInUsd,
3013 | * | nextPositionBorrowingFactor
3014 | | );
3015 | |
3016 | * | return totalBorrowing;
3017 | | }
3018 | |
3019 | | // @dev get the next cumulative borrowing factor
3020 | | // @param dataStore DataStore
3021 | | // @param prices the prices of the market tokens
3022 | | // @param market the market to check
3023 | | // @param longToken the long token of the market
3024 | | // @param shortToken the short token of the market
3025 | | // @param isLong whether to check the long or short side
3026 | * | function getNextCumulativeBorrowingFactor(
3027 | | DataStore dataStore,
3028 | | Market.Props memory market,
3029 | | MarketPrices memory prices,
3030 | | bool isLong
3031 | * | ) internal view returns (uint256, uint256) {
3032 | * | uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(
3033 | * | dataStore,
3034 | * | market.marketToken,
3035 | * | isLong
3036 | | );
3037 | * | uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(
3038 | * | dataStore,
3039 | * | market,
3040 | * | prices,
3041 | * | isLong
3042 | | );
3043 | |
3044 | * | uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(
3045 | * | dataStore,
3046 | * | market.marketToken,
3047 | * | isLong
3048 | | );
3049 | |
3050 | * | uint256 delta = durationInSeconds * borrowingFactorPerSecond;
3051 | * | uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor +
3052 | * | delta;
3053 | * | return (nextCumulativeBorrowingFactor, delta);
3054 | | }
3055 | |
3056 | | // @dev get the borrowing factor per second
3057 | | // @param dataStore DataStore
3058 | | // @param market the market to get the borrowing factor per second for
3059 | | // @param prices the prices of the market tokens
3060 | | // @param isLong whether to get the factor for the long or short side
3061 | * | function getBorrowingFactorPerSecond(
3062 | | DataStore dataStore,
3063 | | Market.Props memory market,
3064 | | MarketPrices memory prices,
3065 | | bool isLong
3066 | * | ) internal view returns (uint256) {
3067 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong);
3068 | |
3069 | * | if (reservedUsd == 0) {
3070 | * | return 0;
3071 | | }
3072 | |
3073 | | // check if the borrowing fee for the smaller side should be skipped
3074 | | // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest
3075 | | // then the borrowing fee would be charged for both sides, this should be very rare
3076 | * | bool skipBorrowingFeeForSmallerSide = dataStore.getBool(
3077 | | Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE
3078 | | );
3079 | * | if (skipBorrowingFeeForSmallerSide) {
3080 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true);
3081 | | uint256 shortOpenInterest = getOpenInterest(
3082 | | dataStore,
3083 | | market,
3084 | | false
3085 | | );
3086 | |
3087 | | // if getting the borrowing factor for longs and if the longOpenInterest
3088 | | // is smaller than the shortOpenInterest, then return zero
3089 | | if (isLong && longOpenInterest < shortOpenInterest) {
3090 | | return 0;
3091 | | }
3092 | |
3093 | | // if getting the borrowing factor for shorts and if the shortOpenInterest
3094 | | // is smaller than the longOpenInterest, then return zero
3095 | | if (!isLong && shortOpenInterest < longOpenInterest) {
3096 | | return 0;
3097 | | }
3098 | | }
3099 | |
3100 | * | uint256 poolUsd = getPoolUsdWithoutPnl(
3101 | * | dataStore,
3102 | * | market,
3103 | * | prices,
3104 | * | isLong,
3105 | * | false
3106 | | );
3107 | |
3108 | * | if (poolUsd == 0) {
3109 | | revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();
3110 | | }
3111 | |
3112 | * | uint256 optimalUsageFactor = getOptimalUsageFactor(
3113 | * | dataStore,
3114 | * | market.marketToken,
3115 | * | isLong
3116 | | );
3117 | |
3118 | * | if (optimalUsageFactor != 0) {
3119 | | return
3120 | | getKinkBorrowingFactor(
3121 | | dataStore,
3122 | | market,
3123 | | isLong,
3124 | | reservedUsd,
3125 | | poolUsd,
3126 | | optimalUsageFactor
3127 | | );
3128 | | }
3129 | |
3130 | * | uint256 borrowingExponentFactor = getBorrowingExponentFactor(
3131 | * | dataStore,
3132 | * | market.marketToken,
3133 | * | isLong
3134 | | );
3135 | * | uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(
3136 | * | reservedUsd,
3137 | * | borrowingExponentFactor
3138 | | );
3139 | |
3140 | * | uint256 reservedUsdToPoolFactor = Precision.toFactor(
3141 | * | reservedUsdAfterExponent,
3142 | * | poolUsd
3143 | | );
3144 | * | uint256 borrowingFactor = getBorrowingFactor(
3145 | * | dataStore,
3146 | * | market.marketToken,
3147 | * | isLong
3148 | | );
3149 | |
3150 | * | return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);
3151 | | }
3152 | |
3153 | | function getKinkBorrowingFactor(
3154 | | DataStore dataStore,
3155 | | Market.Props memory market,
3156 | | bool isLong,
3157 | | uint256 reservedUsd,
3158 | | uint256 poolUsd,
3159 | | uint256 optimalUsageFactor
3160 | | ) internal view returns (uint256) {
3161 | | uint256 usageFactor = getUsageFactor(
3162 | | dataStore,
3163 | | market,
3164 | | isLong,
3165 | | reservedUsd,
3166 | | poolUsd
3167 | | );
3168 | |
3169 | | uint256 baseBorrowingFactor = dataStore.getUint(
3170 | | Keys.baseBorrowingFactorKey(market.marketToken, isLong)
3171 | | );
3172 | |
3173 | | uint256 borrowingFactorPerSecond = Precision.applyFactor(
3174 | | usageFactor,
3175 | | baseBorrowingFactor
3176 | | );
3177 | |
3178 | | if (
3179 | | usageFactor > optimalUsageFactor &&
3180 | | Precision.FLOAT_PRECISION > optimalUsageFactor
3181 | | ) {
3182 | | uint256 diff = usageFactor - optimalUsageFactor;
3183 | |
3184 | | uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(
3185 | | Keys.aboveOptimalUsageBorrowingFactorKey(
3186 | | market.marketToken,
3187 | | isLong
3188 | | )
3189 | | );
3190 | | uint256 additionalBorrowingFactorPerSecond;
3191 | |
3192 | | if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {
3193 | | additionalBorrowingFactorPerSecond =
3194 | | aboveOptimalUsageBorrowingFactor -
3195 | | baseBorrowingFactor;
3196 | | }
3197 | |
3198 | | uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;
3199 | |
3200 | | borrowingFactorPerSecond +=
3201 | | (additionalBorrowingFactorPerSecond * diff) /
3202 | | divisor;
3203 | | }
3204 | |
3205 | | return borrowingFactorPerSecond;
3206 | | }
3207 | |
3208 | * | function distributePositionImpactPool(
3209 | | DataStore dataStore,
3210 | | EventEmitter eventEmitter,
3211 | | address market
3212 | * | ) internal {
3213 | * | (
3214 | * | uint256 distributionAmount,
3215 | * | uint256 nextPositionImpactPoolAmount
3216 | * | ) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);
3217 | |
3218 | * | if (distributionAmount != 0) {
3219 | | applyDeltaToPositionImpactPool(
3220 | | dataStore,
3221 | | eventEmitter,
3222 | | market,
3223 | | -distributionAmount.toInt256()
3224 | | );
3225 | |
3226 | | MarketEventUtils.emitPositionImpactPoolDistributed(
3227 | | eventEmitter,
3228 | | market,
3229 | | distributionAmount,
3230 | | nextPositionImpactPoolAmount
3231 | | );
3232 | | }
3233 | |
3234 | * | dataStore.setUint(
3235 | * | Keys.positionImpactPoolDistributedAtKey(market),
3236 | * | Chain.currentTimestamp()
3237 | | );
3238 | | }
3239 | |
3240 | * | function getNextPositionImpactPoolAmount(
3241 | | DataStore dataStore,
3242 | | address market
3243 | * | ) internal view returns (uint256) {
3244 | * | (
3245 | | ,
3246 | * | /* uint256 distributionAmount */ uint256 nextPositionImpactPoolAmount
3247 | * | ) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);
3248 | |
3249 | * | return nextPositionImpactPoolAmount;
3250 | | }
3251 | |
3252 | | // @return (distributionAmount, nextPositionImpactPoolAmount)
3253 | * | function getPendingPositionImpactPoolDistributionAmount(
3254 | | DataStore dataStore,
3255 | | address market
3256 | * | ) internal view returns (uint256, uint256) {
3257 | * | uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(
3258 | * | dataStore,
3259 | * | market
3260 | | );
3261 | * | if (positionImpactPoolAmount == 0) {
3262 | * | return (0, positionImpactPoolAmount);
3263 | | }
3264 | |
3265 | * | uint256 distributionRate = dataStore.getUint(
3266 | * | Keys.positionImpactPoolDistributionRateKey(market)
3267 | | );
3268 | * | if (distributionRate == 0) {
3269 | * | return (0, positionImpactPoolAmount);
3270 | | }
3271 | |
3272 | | uint256 minPositionImpactPoolAmount = dataStore.getUint(
3273 | | Keys.minPositionImpactPoolAmountKey(market)
3274 | | );
3275 | | if (positionImpactPoolAmount <= minPositionImpactPoolAmount) {
3276 | | return (0, positionImpactPoolAmount);
3277 | | }
3278 | |
3279 | | uint256 maxDistributionAmount = positionImpactPoolAmount -
3280 | | minPositionImpactPoolAmount;
3281 | |
3282 | | uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(
3283 | | dataStore,
3284 | | market
3285 | | );
3286 | | uint256 distributionAmount = Precision.applyFactor(
3287 | | durationInSeconds,
3288 | | distributionRate
3289 | | );
3290 | |
3291 | | if (distributionAmount > maxDistributionAmount) {
3292 | | distributionAmount = maxDistributionAmount;
3293 | | }
3294 | |
3295 | | return (
3296 | | distributionAmount,
3297 | | positionImpactPoolAmount - distributionAmount
3298 | | );
3299 | | }
3300 | |
3301 | | function getSecondsSincePositionImpactPoolDistributed(
3302 | | DataStore dataStore,
3303 | | address market
3304 | | ) internal view returns (uint256) {
3305 | | uint256 distributedAt = dataStore.getUint(
3306 | | Keys.positionImpactPoolDistributedAtKey(market)
3307 | | );
3308 | | if (distributedAt == 0) {
3309 | | return 0;
3310 | | }
3311 | | return Chain.currentTimestamp() - distributedAt;
3312 | | }
3313 | |
3314 | | // @dev get the total pending borrowing fees
3315 | | // @param dataStore DataStore
3316 | | // @param market the market to check
3317 | | // @param longToken the long token of the market
3318 | | // @param shortToken the short token of the market
3319 | | // @param isLong whether to check the long or short side
3320 | * | function getTotalPendingBorrowingFees(
3321 | | DataStore dataStore,
3322 | | Market.Props memory market,
3323 | | MarketPrices memory prices,
3324 | | bool isLong
3325 | * | ) internal view returns (uint256) {
3326 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong);
3327 | |
3328 | * | (
3329 | * | uint256 nextCumulativeBorrowingFactor /* uint256 delta */,
3330 | |
3331 | * | ) = getNextCumulativeBorrowingFactor(dataStore, market, prices, isLong);
3332 | |
3333 | * | uint256 totalBorrowing = getTotalBorrowing(
3334 | * | dataStore,
3335 | * | market.marketToken,
3336 | * | isLong
3337 | | );
3338 | |
3339 | * | return
3340 | * | Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) -
3341 | * | totalBorrowing;
3342 | | }
3343 | |
3344 | | // @dev get the total borrowing value
3345 | | // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30)
3346 | | // for all positions of the market
3347 | | // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 1000 * (10 ** 30)
3348 | | // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues
3349 | | // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 1000 * (10 ** 30)) => 1,157,920,900,000 USD
3350 | | // @param dataStore DataStore
3351 | | // @param market the market to check
3352 | | // @param isLong whether to check the long or short side
3353 | | // @return the total borrowing value
3354 | * | function getTotalBorrowing(
3355 | | DataStore dataStore,
3356 | | address market,
3357 | | bool isLong
3358 | * | ) internal view returns (uint256) {
3359 | * | return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));
3360 | | }
3361 | |
3362 | | // @dev set the total borrowing value
3363 | | // @param dataStore DataStore
3364 | | // @param market the market to set
3365 | | // @param isLong whether to set the long or short side
3366 | | // @param value the value to set to
3367 | * | function setTotalBorrowing(
3368 | | DataStore dataStore,
3369 | | address market,
3370 | | bool isLong,
3371 | | uint256 value
3372 | * | ) internal returns (uint256) {
3373 | * | return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);
3374 | | }
3375 | |
3376 | | // @dev convert a USD value to number of market tokens
3377 | | // @param usdValue the input USD value
3378 | | // @param poolValue the value of the pool
3379 | | // @param supply the supply of market tokens
3380 | | // @return the number of market tokens
3381 | * | function usdToMarketTokenAmount(
3382 | | uint256 usdValue,
3383 | | uint256 poolValue,
3384 | | uint256 supply
3385 | * | ) internal pure returns (uint256) {
3386 | | // if the supply and poolValue is zero, use 1 USD as the token price
3387 | * | if (supply == 0 && poolValue == 0) {
3388 | | return Precision.floatToWei(usdValue);
3389 | | }
3390 | |
3391 | | // if the supply is zero and the poolValue is more than zero,
3392 | | // then include the poolValue for the amount of tokens minted so that
3393 | | // the market token price after mint would be 1 USD
3394 | * | if (supply == 0 && poolValue > 0) {
3395 | | return Precision.floatToWei(poolValue + usdValue);
3396 | | }
3397 | |
3398 | | // round market tokens down
3399 | * | return Precision.mulDiv(supply, usdValue, poolValue);
3400 | | }
3401 | |
3402 | | // @dev convert a number of market tokens to its USD value
3403 | | // @param marketTokenAmount the input number of market tokens
3404 | | // @param poolValue the value of the pool
3405 | | // @param supply the supply of market tokens
3406 | | // @return the USD value of the market tokens
3407 | * | function marketTokenAmountToUsd(
3408 | | uint256 marketTokenAmount,
3409 | | uint256 poolValue,
3410 | | uint256 supply
3411 | * | ) internal pure returns (uint256) {
3412 | * | if (supply == 0) {
3413 | | revert Errors.EmptyMarketTokenSupply();
3414 | | }
3415 | |
3416 | * | return Precision.mulDiv(poolValue, marketTokenAmount, supply);
3417 | | }
3418 | |
3419 | | // @dev validate that the specified market exists and is enabled
3420 | | // @param dataStore DataStore
3421 | | // @param marketAddress the address of the market
3422 | * | function validateEnabledMarket(
3423 | | DataStore dataStore,
3424 | | address marketAddress
3425 | * | ) internal view {
3426 | * | Market.Props memory market = MarketStoreUtils.get(
3427 | * | dataStore,
3428 | * | marketAddress
3429 | | );
3430 | * | validateEnabledMarket(dataStore, market);
3431 | | }
3432 | |
3433 | | // @dev validate that the specified market exists and is enabled
3434 | | // @param dataStore DataStore
3435 | | // @param market the market to check
3436 | * | function validateEnabledMarket(
3437 | | DataStore dataStore,
3438 | | Market.Props memory market
3439 | * | ) internal view {
3440 | * | if (market.marketToken == address(0)) {
3441 | | revert Errors.EmptyMarket();
3442 | | }
3443 | |
3444 | * | bool isMarketDisabled = dataStore.getBool(
3445 | * | Keys.isMarketDisabledKey(market.marketToken)
3446 | | );
3447 | * | if (isMarketDisabled) {
3448 | | revert Errors.DisabledMarket(market.marketToken);
3449 | | }
3450 | | }
3451 | |
3452 | | // @dev validate that the positions can be opened in the given market
3453 | | // @param market the market to check
3454 | * | function validatePositionMarket(
3455 | | DataStore dataStore,
3456 | | Market.Props memory market
3457 | | ) internal view {
3458 | * | validateEnabledMarket(dataStore, market);
3459 | |
3460 | * | if (isSwapOnlyMarket(market)) {
3461 | | revert Errors.InvalidPositionMarket(market.marketToken);
3462 | | }
3463 | | }
3464 | |
3465 | * | function validatePositionMarket(
3466 | | DataStore dataStore,
3467 | | address marketAddress
3468 | * | ) internal view {
3469 | * | Market.Props memory market = MarketStoreUtils.get(
3470 | * | dataStore,
3471 | * | marketAddress
3472 | | );
3473 | * | validatePositionMarket(dataStore, market);
3474 | | }
3475 | |
3476 | | // @dev check if a market only supports swaps and not positions
3477 | | // @param market the market to check
3478 | * | function isSwapOnlyMarket(
3479 | | Market.Props memory market
3480 | * | ) internal pure returns (bool) {
3481 | * | return market.indexToken == address(0);
3482 | | }
3483 | |
3484 | | // @dev check if the given token is a collateral token of the market
3485 | | // @param market the market to check
3486 | | // @param token the token to check
3487 | * | function isMarketCollateralToken(
3488 | | Market.Props memory market,
3489 | | address token
3490 | * | ) internal pure returns (bool) {
3491 | * | return token == market.longToken || token == market.shortToken;
3492 | | }
3493 | |
3494 | | // @dev validate if the given token is a collateral token of the market
3495 | | // @param market the market to check
3496 | | // @param token the token to check
3497 | * | function validateMarketCollateralToken(
3498 | | Market.Props memory market,
3499 | | address token
3500 | | ) internal pure {
3501 | * | if (!isMarketCollateralToken(market, token)) {
3502 | | revert Errors.InvalidCollateralTokenForMarket(
3503 | | market.marketToken,
3504 | | token
3505 | | );
3506 | | }
3507 | | }
3508 | |
3509 | | // @dev get the enabled market, revert if the market does not exist or is not enabled
3510 | | // @param dataStore DataStore
3511 | | // @param marketAddress the address of the market
3512 | * | function getEnabledMarket(
3513 | | DataStore dataStore,
3514 | | address marketAddress
3515 | * | ) internal view returns (Market.Props memory) {
3516 | * | Market.Props memory market = MarketStoreUtils.get(
3517 | * | dataStore,
3518 | * | marketAddress
3519 | | );
3520 | * | validateEnabledMarket(dataStore, market);
3521 | * | return market;
3522 | | }
3523 | |
3524 | * | function getSwapPathMarket(
3525 | | DataStore dataStore,
3526 | | address marketAddress
3527 | * | ) internal view returns (Market.Props memory) {
3528 | * | Market.Props memory market = MarketStoreUtils.get(
3529 | * | dataStore,
3530 | * | marketAddress
3531 | | );
3532 | * | validateSwapMarket(dataStore, market);
3533 | * | return market;
3534 | | }
3535 | |
3536 | | // @dev get a list of market values based on an input array of market addresses
3537 | | // @param swapPath list of market addresses
3538 | * | function getSwapPathMarkets(
3539 | | DataStore dataStore,
3540 | | address[] memory swapPath
3541 | * | ) internal view returns (Market.Props[] memory) {
3542 | * | Market.Props[] memory markets = new Market.Props[](swapPath.length);
3543 | |
3544 | * | for (uint256 i; i < swapPath.length; i++) {
3545 | * | address marketAddress = swapPath[i];
3546 | * | markets[i] = getSwapPathMarket(dataStore, marketAddress);
3547 | | }
3548 | |
3549 | * | return markets;
3550 | | }
3551 | |
3552 | * | function validateSwapPath(
3553 | | DataStore dataStore,
3554 | | address[] memory swapPath
3555 | * | ) internal view {
3556 | * | uint256 maxSwapPathLength = dataStore.getUint(
3557 | | Keys.MAX_SWAP_PATH_LENGTH
3558 | | );
3559 | * | if (swapPath.length > maxSwapPathLength) {
3560 | | revert Errors.MaxSwapPathLengthExceeded(
3561 | | swapPath.length,
3562 | | maxSwapPathLength
3563 | | );
3564 | | }
3565 | |
3566 | * | for (uint256 i; i < swapPath.length; i++) {
3567 | * | address marketAddress = swapPath[i];
3568 | * | validateSwapMarket(dataStore, marketAddress);
3569 | | }
3570 | | }
3571 | |
3572 | | // @dev validate that the pending pnl is below the allowed amount
3573 | | // @param dataStore DataStore
3574 | | // @param market the market to check
3575 | | // @param prices the prices of the market tokens
3576 | | // @param pnlFactorType the pnl factor type to check
3577 | | // function validateMaxPnl(
3578 | | // DataStore dataStore,
3579 | | // Market.Props memory market,
3580 | | // MarketPrices memory prices,
3581 | | // bytes32 pnlFactorTypeForLongs,
3582 | | // bytes32 pnlFactorTypeForShorts
3583 | | // ) internal view {
3584 | | // (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(
3585 | | // dataStore,
3586 | | // market,
3587 | | // prices,
3588 | | // true,
3589 | | // pnlFactorTypeForLongs
3590 | | // );
3591 | |
3592 | | // if (isPnlFactorExceededForLongs) {
3593 | | // revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);
3594 | | // }
3595 | |
3596 | | // (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(
3597 | | // dataStore,
3598 | | // market,
3599 | | // prices,
3600 | | // false,
3601 | | // pnlFactorTypeForShorts
3602 | | // );
3603 | |
3604 | | // if (isPnlFactorExceededForShorts) {
3605 | | // revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);
3606 | | // }
3607 | | // }
3608 | |
3609 | * | function validateMaxPnl(
3610 | | DataStore dataStore,
3611 | | Market.Props memory market,
3612 | | MarketPrices memory prices,
3613 | | bytes32 pnlFactorTypeForLongs,
3614 | | bytes32 pnlFactorTypeForShorts
3615 | * | ) internal view {
3616 | * | (
3617 | * | bool isPnlFactorExceededForLongs,
3618 | * | int256 pnlToPoolFactorForLongs,
3619 | * | uint256 maxPnlFactorForLongs
3620 | * | ) = isPnlFactorExceeded(
3621 | * | dataStore,
3622 | * | market,
3623 | * | prices,
3624 | * | true,
3625 | * | pnlFactorTypeForLongs
3626 | | );
3627 | |
3628 | |
3629 | * | if (isPnlFactorExceededForLongs) {
3630 | * | revert Errors.PnlFactorExceededForLongs(
3631 | * | pnlToPoolFactorForLongs,
3632 | * | maxPnlFactorForLongs
3633 | | );
3634 | | }
3635 | |
3636 | * | (
3637 | * | bool isPnlFactorExceededForShorts,
3638 | * | int256 pnlToPoolFactorForShorts,
3639 | * | uint256 maxPnlFactorForShorts
3640 | * | ) = isPnlFactorExceeded(
3641 | * | dataStore,
3642 | * | market,
3643 | * | prices,
3644 | * | false,
3645 | * | pnlFactorTypeForShorts
3646 | | );
3647 | |
3648 | |
3649 | * | if (isPnlFactorExceededForShorts) {
3650 | | revert Errors.PnlFactorExceededForShorts(
3651 | | pnlToPoolFactorForShorts,
3652 | | maxPnlFactorForShorts
3653 | | );
3654 | | }
3655 | | }
3656 | |
3657 | | // @dev check if the pending pnl exceeds the allowed amount
3658 | | // @param dataStore DataStore
3659 | | // @param oracle Oracle
3660 | | // @param market the market to check
3661 | | // @param isLong whether to check the long or short side
3662 | | // @param pnlFactorType the pnl factor type to check
3663 | * | function isPnlFactorExceeded(
3664 | | DataStore dataStore,
3665 | | Oracle oracle,
3666 | | address market,
3667 | | bool isLong,
3668 | | bytes32 pnlFactorType
3669 | * | ) internal view returns (bool, int256, uint256) {
3670 | * | Market.Props memory _market = getEnabledMarket(dataStore, market);
3671 | * | MarketPrices memory prices = getMarketPrices(oracle, _market);
3672 | |
3673 | * | return
3674 | * | isPnlFactorExceeded(
3675 | * | dataStore,
3676 | * | _market,
3677 | * | prices,
3678 | * | isLong,
3679 | * | pnlFactorType
3680 | | );
3681 | | }
3682 | |
3683 | | // @dev check if the pending pnl exceeds the allowed amount
3684 | | // @param dataStore DataStore
3685 | | // @param _market the market to check
3686 | | // @param prices the prices of the market tokens
3687 | | // @param isLong whether to check the long or short side
3688 | | // @param pnlFactorType the pnl factor type to check
3689 | | // function isPnlFactorExceeded(
3690 | | // DataStore dataStore,
3691 | | // Market.Props memory market,
3692 | | // MarketPrices memory prices,
3693 | | // bool isLong,
3694 | | // bytes32 pnlFactorType
3695 | | // ) internal view returns (bool, int256, uint256) {
3696 | | // int256 pnlToPoolFactor = getPnlToPoolFactor(
3697 | | // dataStore,
3698 | | // market,
3699 | | // prices,
3700 | | // isLong,
3701 | | // true
3702 | | // );
3703 | | // uint256 maxPnlFactor = getMaxPnlFactor(
3704 | | // dataStore,
3705 | | // pnlFactorType,
3706 | | // market.marketToken,
3707 | | // isLong
3708 | | // );
3709 | |
3710 | | // bool isExceeded = pnlToPoolFactor > 0 &&
3711 | | // pnlToPoolFactor.toUint256() > maxPnlFactor;
3712 | |
3713 | | // return (isExceeded, pnlToPoolFactor, maxPnlFactor);
3714 | | // }
3715 | |
3716 | * | function isPnlFactorExceeded(
3717 | | DataStore dataStore,
3718 | | Market.Props memory market,
3719 | | MarketPrices memory prices,
3720 | | bool isLong,
3721 | | bytes32 pnlFactorType
3722 | * | ) internal view returns (bool, int256, uint256) {
3723 | |
3724 | * | int256 pnlToPoolFactor = getPnlToPoolFactor(
3725 | * | dataStore,
3726 | * | market,
3727 | * | prices,
3728 | * | isLong,
3729 | * | true
3730 | | );
3731 | |
3732 | * | uint256 maxPnlFactor = getMaxPnlFactor(
3733 | * | dataStore,
3734 | * | pnlFactorType,
3735 | * | market.marketToken,
3736 | * | isLong
3737 | | );
3738 | |
3739 | * | bool isExceeded = pnlToPoolFactor > 0 &&
3740 | * | pnlToPoolFactor.toUint256() > maxPnlFactor;
3741 | |
3742 | * | return (isExceeded, pnlToPoolFactor, maxPnlFactor);
3743 | | }
3744 | |
3745 | * | function getUiFeeFactor(
3746 | | DataStore dataStore,
3747 | | address account
3748 | * | ) internal view returns (uint256) {
3749 | * | uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);
3750 | * | uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));
3751 | |
3752 | * | return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;
3753 | | }
3754 | |
3755 | | function setUiFeeFactor(
3756 | | DataStore dataStore,
3757 | | EventEmitter eventEmitter,
3758 | | address account,
3759 | | uint256 uiFeeFactor
3760 | | ) internal {
3761 | | uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);
3762 | |
3763 | | if (uiFeeFactor > maxUiFeeFactor) {
3764 | | revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);
3765 | | }
3766 | |
3767 | | dataStore.setUint(Keys.uiFeeFactorKey(account), uiFeeFactor);
3768 | |
3769 | | MarketEventUtils.emitUiFeeFactorUpdated(
3770 | | eventEmitter,
3771 | | account,
3772 | | uiFeeFactor
3773 | | );
3774 | | }
3775 | |
3776 | * | function validateMarketTokenBalance(
3777 | | DataStore dataStore,
3778 | | Market.Props[] memory markets
3779 | | ) internal view {
3780 | * | for (uint256 i; i < markets.length; i++) {
3781 | * | validateMarketTokenBalance(dataStore, markets[i]);
3782 | | }
3783 | | }
3784 | |
3785 | * | function validateMarketTokenBalance(
3786 | | DataStore dataStore,
3787 | | address _market
3788 | * | ) internal view {
3789 | * | Market.Props memory market = getEnabledMarket(dataStore, _market);
3790 | * | validateMarketTokenBalance(dataStore, market);
3791 | | }
3792 | |
3793 | * | function validateMarketTokenBalance(
3794 | | DataStore dataStore,
3795 | | Market.Props memory market
3796 | | ) internal view {
3797 | * | validateMarketTokenBalance(dataStore, market, market.longToken);
3798 | |
3799 | * | if (market.longToken == market.shortToken) {
3800 | * | return;
3801 | | }
3802 | |
3803 | * | validateMarketTokenBalance(dataStore, market, market.shortToken);
3804 | | }
3805 | |
3806 | * | function validateMarketTokenBalance(
3807 | | DataStore dataStore,
3808 | | Market.Props memory market,
3809 | | address token
3810 | * | ) internal view {
3811 | * | if (market.marketToken == address(0) || token == address(0)) {
3812 | | revert Errors.EmptyAddressInMarketTokenBalanceValidation(
3813 | | market.marketToken,
3814 | | token
3815 | | );
3816 | | }
3817 | |
3818 | * | uint256 balance = IERC20(token).balanceOf(market.marketToken);
3819 | * | uint256 expectedMinBalance = getExpectedMinTokenBalance(
3820 | * | dataStore,
3821 | * | market,
3822 | * | token
3823 | | );
3824 | |
3825 | * | if (balance < expectedMinBalance) {
3826 | * | revert Errors.InvalidMarketTokenBalance(
3827 | * | market.marketToken,
3828 | * | token,
3829 | * | balance,
3830 | * | expectedMinBalance
3831 | | );
3832 | | }
3833 | |
3834 | | // funding fees can be claimed even if the collateral for positions that should pay funding fees
3835 | | // hasn't been reduced yet
3836 | | // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation
3837 | | // and validated separately
3838 | |
3839 | | // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the
3840 | | // longToken and shortToken
3841 | * | uint256 collateralAmount = getCollateralSum(
3842 | * | dataStore,
3843 | * | market.marketToken,
3844 | * | token,
3845 | * | true,
3846 | * | 1
3847 | | );
3848 | * | collateralAmount += getCollateralSum(
3849 | * | dataStore,
3850 | * | market.marketToken,
3851 | * | token,
3852 | * | false,
3853 | * | 1
3854 | | );
3855 | |
3856 | * | if (balance < collateralAmount) {
3857 | | revert Errors.InvalidMarketTokenBalanceForCollateralAmount(
3858 | | market.marketToken,
3859 | | token,
3860 | | balance,
3861 | | collateralAmount
3862 | | );
3863 | | }
3864 | |
3865 | * | uint256 claimableFundingFeeAmount = dataStore.getUint(
3866 | * | Keys.claimableFundingAmountKey(market.marketToken, token)
3867 | | );
3868 | |
3869 | | // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance
3870 | | // but this should be very rare
3871 | * | if (balance < claimableFundingFeeAmount) {
3872 | | revert Errors.InvalidMarketTokenBalanceForClaimableFunding(
3873 | | market.marketToken,
3874 | | token,
3875 | | balance,
3876 | | claimableFundingFeeAmount
3877 | | );
3878 | | }
3879 | | }
3880 | |
3881 | * | function getExpectedMinTokenBalance(
3882 | | DataStore dataStore,
3883 | | Market.Props memory market,
3884 | | address token
3885 | * | ) internal view returns (uint256) {
3886 | * | GetExpectedMinTokenBalanceCache memory cache;
3887 | |
3888 | | // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2
3889 | | // for markets with the same long and short token
3890 | * | cache.poolAmount = dataStore.getUint(
3891 | * | Keys.poolAmountKey(market.marketToken, token)
3892 | | );
3893 | * | cache.swapImpactPoolAmount = getSwapImpactPoolAmount(
3894 | * | dataStore,
3895 | * | market.marketToken,
3896 | * | token
3897 | | );
3898 | * | cache.claimableCollateralAmount = dataStore.getUint(
3899 | * | Keys.claimableCollateralAmountKey(market.marketToken, token)
3900 | | );
3901 | * | cache.claimableFeeAmount = dataStore.getUint(
3902 | * | Keys.claimableFeeAmountKey(market.marketToken, token)
3903 | | );
3904 | * | cache.claimableUiFeeAmount = dataStore.getUint(
3905 | * | Keys.claimableUiFeeAmountKey(market.marketToken, token)
3906 | | );
3907 | * | cache.affiliateRewardAmount = dataStore.getUint(
3908 | * | Keys.affiliateRewardKey(market.marketToken, token)
3909 | | );
3910 | |
3911 | | // funding fees are excluded from this summation as claimable funding fees
3912 | | // are incremented without a corresponding decrease of the collateral of
3913 | | // other positions, the collateral of other positions is decreased when
3914 | | // those positions are updated
3915 | * | return
3916 | * | cache.poolAmount +
3917 | * | cache.swapImpactPoolAmount +
3918 | * | cache.claimableCollateralAmount +
3919 | * | cache.claimableFeeAmount +
3920 | * | cache.claimableUiFeeAmount +
3921 | * | cache.affiliateRewardAmount;
3922 | | }
3923 | | }
3924 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/migration/TimestampInitializer.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../chain/Chain.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../event/EventEmitter.sol";
8 | | import "../role/RoleModule.sol";
9 | | import "../order/OrderStoreUtils.sol";
10 | | import "../position/PositionStoreUtils.sol";
11 | |
12 | | contract TimestampInitializer is RoleModule {
13 | | using EventUtils for EventUtils.AddressItems;
14 | | using EventUtils for EventUtils.UintItems;
15 | | using EventUtils for EventUtils.IntItems;
16 | | using EventUtils for EventUtils.BoolItems;
17 | | using EventUtils for EventUtils.Bytes32Items;
18 | | using EventUtils for EventUtils.BytesItems;
19 | | using EventUtils for EventUtils.StringItems;
20 | |
21 | | DataStore public immutable dataStore;
22 | | EventEmitter public immutable eventEmitter;
23 | |
24 | | constructor(
25 | | RoleStore _roleStore,
26 | | DataStore _dataStore,
27 | | EventEmitter _eventEmitter
28 | | ) RoleModule(_roleStore) {
29 | | dataStore = _dataStore;
30 | | eventEmitter = _eventEmitter;
31 | | }
32 | |
33 | |
34 | | function initializeOrderTimestamps(uint256 start, uint256 end) external onlyConfigKeeper {
35 | | bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end);
36 | | uint256 currentTimestamp = Chain.currentTimestamp();
37 | |
38 | | for (uint256 i; i < keys.length; i++) {
39 | | bytes32 key = keys[i];
40 | |
41 | | uint256 updatedAtTime = dataStore.getUint(
42 | | keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME))
43 | | );
44 | |
45 | | if (updatedAtTime == 0) {
46 | |
47 | | dataStore.setUint(
48 | | keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME)),
49 | | currentTimestamp
50 | | );
51 | |
52 | | EventUtils.EventLogData memory eventData;
53 | | eventData.bytes32Items.initItems(1);
54 | | eventData.bytes32Items.setItem(0, "key", key);
55 | |
56 | | eventData.uintItems.initItems(1);
57 | | eventData.uintItems.setItem(0, "updatedAtTime", currentTimestamp);
58 | |
59 | | eventEmitter.emitEventLog(
60 | | "InitializeOrderUpdatedAtTime",
61 | | eventData
62 | | );
63 | | }
64 | | }
65 | | }
66 | |
67 | | function initializePositionTimestamps(uint256 start, uint256 end) external onlyConfigKeeper {
68 | | bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end);
69 | | uint256 currentTimestamp = Chain.currentTimestamp();
70 | |
71 | | for (uint256 i; i < keys.length; i++) {
72 | | bytes32 key = keys[i];
73 | |
74 | | uint256 increasedAtTime = dataStore.getUint(
75 | | keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME))
76 | | );
77 | |
78 | | if (increasedAtTime == 0) {
79 | | dataStore.setUint(
80 | | keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME)),
81 | | currentTimestamp
82 | | );
83 | |
84 | | EventUtils.EventLogData memory eventData;
85 | | eventData.bytes32Items.initItems(1);
86 | | eventData.bytes32Items.setItem(0, "key", key);
87 | |
88 | | eventData.uintItems.initItems(1);
89 | | eventData.uintItems.setItem(0, "increasedAtTime", currentTimestamp);
90 | |
91 | | eventEmitter.emitEventLog(
92 | | "InitializePositionIncreasedAtTime",
93 | | eventData
94 | | );
95 | | }
96 | |
97 | | uint256 decreasedAtTime = dataStore.getUint(
98 | | keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME))
99 | | );
100 | |
101 | | if (decreasedAtTime == 0) {
102 | | dataStore.setUint(
103 | | keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME)),
104 | | currentTimestamp
105 | | );
106 | |
107 | | EventUtils.EventLogData memory eventData;
108 | | eventData.bytes32Items.initItems(1);
109 | | eventData.bytes32Items.setItem(0, "key", key);
110 | |
111 | | eventData.uintItems.initItems(1);
112 | | eventData.uintItems.setItem(0, "decreasedAtTime", currentTimestamp);
113 | |
114 | | eventEmitter.emitEventLog(
115 | | "InitializePositionDecreasedAtTime",
116 | | eventData
117 | | );
118 | | }
119 | | }
120 | | }
121 | |
122 | | }
123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/Governable.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../error/Errors.sol";
6 | |
7 | | // @title Governable
8 | | // @dev Contract to allow for governance restricted functions
9 | | contract Governable {
10 | | address public gov;
11 | | address public pendingGov;
12 | |
13 | | event SetGov(address prevGov, address nextGov);
14 | |
15 | | constructor() {
16 | | _setGov(msg.sender);
17 | | }
18 | |
19 | | modifier onlyGov() {
20 | | if (msg.sender != gov) {
21 | | revert Errors.Unauthorized(msg.sender, "GOV");
22 | | }
23 | | _;
24 | | }
25 | |
26 | | function transferOwnership(address _newGov) external onlyGov {
27 | | pendingGov = _newGov;
28 | | }
29 | |
30 | | function acceptOwnership() external {
31 | | if (msg.sender != pendingGov) {
32 | | revert Errors.Unauthorized(msg.sender, "PendingGov");
33 | | }
34 | |
35 | | _setGov(msg.sender);
36 | | }
37 | |
38 | | // @dev updates the gov value to the input _gov value
39 | | // @param _gov the value to update to
40 | | function _setGov(address _gov) internal {
41 | | address prevGov = gov;
42 | | gov = _gov;
43 | |
44 | | emit SetGov(prevGov, _gov);
45 | | }
46 | | }
47 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MintableToken.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6 | |
7 | | // @title MintableToken
8 | | // @dev Mock mintable token for testing and testnets
9 | * | contract MintableToken is ERC20 {
10 | | uint8 private _decimals;
11 | |
12 | | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
13 | | _decimals = decimals_;
14 | | }
15 | |
16 | | function decimals() public view virtual override returns (uint8) {
17 | | return _decimals;
18 | | }
19 | |
20 | | // @dev mint tokens to an account
21 | | // @param account the account to mint to
22 | | // @param amount the amount of tokens to mint
23 | | function mint(address account, uint256 amount) external {
24 | | _mint(account, amount);
25 | | }
26 | |
27 | | // @dev burn tokens from an account
28 | | // @param account the account to burn tokens for
29 | | // @param amount the amount of tokens to burn
30 | | function burn(address account, uint256 amount) external {
31 | | _burn(account, amount);
32 | | }
33 | | }
34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MockDataStreamVerifier.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../oracle/IChainlinkDataStreamVerifier.sol";
6 | |
7 | * | contract MockDataStreamVerifier is IChainlinkDataStreamVerifier {
8 | | function verify(
9 | | bytes calldata payload,
10 | | bytes calldata parameterPayload
11 | | ) external payable returns (bytes memory) {
12 | | (address feeToken) = abi.decode(parameterPayload, (address));
13 | | require(feeToken == 0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf, "invalid fee token");
14 | |
15 | | return payload;
16 | | }
17 | | }
18 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MockPriceFeed.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../oracle/IPriceFeed.sol";
6 | |
7 | | // @title MockPriceFeed
8 | | // @dev Mock price feed for testing and testnets
9 | * | contract MockPriceFeed is IPriceFeed {
10 | | int256 public answer;
11 | |
12 | | // @dev set answer
13 | | // @param _answer the answer to set to
14 | | function setAnswer(int256 _answer) external {
15 | | answer = _answer;
16 | | }
17 | |
18 | | function latestAnswer() external view returns (int256) {
19 | | return answer;
20 | | }
21 | |
22 | | // @dev get the latest data
23 | | // @return (roundId, answer, startedAt, updatedAt, answeredInRound)
24 | | function latestRoundData() external view returns (
25 | | uint80,
26 | | int256,
27 | | uint256,
28 | | uint256,
29 | | uint80
30 | | ) {
31 | | return (
32 | | uint80(0), // roundId
33 | | answer, // answer
34 | | 0, // startedAt
35 | | block.timestamp - 60, // updatedAt
36 | | uint80(0) // answeredInRound
37 | | );
38 | | }
39 | | }
40 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/Multicall3.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | /// @title Multicall3
5 | | /// @notice Aggregate results from multiple function calls
6 | | /// @dev Multicall & Multicall2 backwards-compatible
7 | | /// @dev Aggregate methods are marked `payable` to save 24 gas per call
8 | | /// @author Michael Elliot <mike@makerdao.com>
9 | | /// @author Joshua Levine <joshua@makerdao.com>
10 | | /// @author Nick Johnson <arachnid@notdot.net>
11 | | /// @author Andreas Bigger <andreas@nascent.xyz>
12 | | /// @author Matt Solomon <matt@mattsolomon.dev>
13 | * | contract Multicall3 {
14 | | struct Call {
15 | | address target;
16 | | bytes callData;
17 | | }
18 | |
19 | | struct Call3 {
20 | | address target;
21 | | bool allowFailure;
22 | | bytes callData;
23 | | }
24 | |
25 | | struct Call3Value {
26 | | address target;
27 | | bool allowFailure;
28 | | uint256 value;
29 | | bytes callData;
30 | | }
31 | |
32 | | struct Result {
33 | | bool success;
34 | | bytes returnData;
35 | | }
36 | |
37 | | /// @notice Backwards-compatible call aggregation with Multicall
38 | | /// @param calls An array of Call structs
39 | | /// @return blockNumber The block number where the calls were executed
40 | | /// @return returnData An array of bytes containing the responses
41 | | function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {
42 | | blockNumber = block.number;
43 | | uint256 length = calls.length;
44 | | returnData = new bytes[](length);
45 | | Call calldata call;
46 | | for (uint256 i; i < length;) {
47 | | bool success;
48 | | call = calls[i];
49 | | (success, returnData[i]) = call.target.call(call.callData);
50 | | require(success, "Multicall3: call failed");
51 | | unchecked { ++i; }
52 | | }
53 | | }
54 | |
55 | | /// @notice Backwards-compatible with Multicall2
56 | | /// @notice Aggregate calls without requiring success
57 | | /// @param requireSuccess If true, require all calls to succeed
58 | | /// @param calls An array of Call structs
59 | | /// @return returnData An array of Result structs
60 | | function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) {
61 | | uint256 length = calls.length;
62 | | returnData = new Result[](length);
63 | | Call calldata call;
64 | | for (uint256 i; i < length;) {
65 | | Result memory result = returnData[i];
66 | | call = calls[i];
67 | | (result.success, result.returnData) = call.target.call(call.callData);
68 | | if (requireSuccess) require(result.success, "Multicall3: call failed");
69 | | unchecked { ++i; }
70 | | }
71 | | }
72 | |
73 | | /// @notice Backwards-compatible with Multicall2
74 | | /// @notice Aggregate calls and allow failures using tryAggregate
75 | | /// @param calls An array of Call structs
76 | | /// @return blockNumber The block number where the calls were executed
77 | | /// @return blockHash The hash of the block where the calls were executed
78 | | /// @return returnData An array of Result structs
79 | | function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
80 | | blockNumber = block.number;
81 | | blockHash = blockhash(block.number);
82 | | returnData = tryAggregate(requireSuccess, calls);
83 | | }
84 | |
85 | | /// @notice Backwards-compatible with Multicall2
86 | | /// @notice Aggregate calls and allow failures using tryAggregate
87 | | /// @param calls An array of Call structs
88 | | /// @return blockNumber The block number where the calls were executed
89 | | /// @return blockHash The hash of the block where the calls were executed
90 | | /// @return returnData An array of Result structs
91 | | function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
92 | | (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
93 | | }
94 | |
95 | | /// @notice Aggregate calls, ensuring each returns success if required
96 | | /// @param calls An array of Call3 structs
97 | | /// @return returnData An array of Result structs
98 | | function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {
99 | | uint256 length = calls.length;
100 | | returnData = new Result[](length);
101 | | Call3 calldata calli;
102 | | for (uint256 i; i < length;) {
103 | | Result memory result = returnData[i];
104 | | calli = calls[i];
105 | | (result.success, result.returnData) = calli.target.call(calli.callData);
106 | | assembly {
107 | | // Revert if the call fails and failure is not allowed
108 | | // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
109 | | if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
110 | | // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
111 | | mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
112 | | // set data offset
113 | | mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
114 | | // set length of revert string
115 | | mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
116 | | // set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
117 | | mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
118 | | revert(0x00, 0x64)
119 | | }
120 | | }
121 | | unchecked { ++i; }
122 | | }
123 | | }
124 | |
125 | | /// @notice Aggregate calls with a msg value
126 | | /// @notice Reverts if msg.value is less than the sum of the call values
127 | | /// @param calls An array of Call3Value structs
128 | | /// @return returnData An array of Result structs
129 | | function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {
130 | | uint256 valAccumulator;
131 | | uint256 length = calls.length;
132 | | returnData = new Result[](length);
133 | | Call3Value calldata calli;
134 | | for (uint256 i; i < length;) {
135 | | Result memory result = returnData[i];
136 | | calli = calls[i];
137 | | uint256 val = calli.value;
138 | | // Humanity will be a Type V Kardashev Civilization before this overflows - andreas
139 | | // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
140 | | unchecked { valAccumulator += val; }
141 | | (result.success, result.returnData) = calli.target.call{value: val}(calli.callData);
142 | | assembly {
143 | | // Revert if the call fails and failure is not allowed
144 | | // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
145 | | if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
146 | | // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
147 | | mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
148 | | // set data offset
149 | | mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
150 | | // set length of revert string
151 | | mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
152 | | // set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
153 | | mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
154 | | revert(0x00, 0x84)
155 | | }
156 | | }
157 | | unchecked { ++i; }
158 | | }
159 | | // Finally, make sure the msg.value = SUM(call[0...i].value)
160 | | require(msg.value == valAccumulator, "Multicall3: value mismatch");
161 | | }
162 | |
163 | | /// @notice Returns the block hash for the given block number
164 | | /// @param blockNumber The block number
165 | | function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
166 | | blockHash = blockhash(blockNumber);
167 | | }
168 | |
169 | | /// @notice Returns the block number
170 | | function getBlockNumber() public view returns (uint256 blockNumber) {
171 | | blockNumber = block.number;
172 | | }
173 | |
174 | | /// @notice Returns the block coinbase
175 | | function getCurrentBlockCoinbase() public view returns (address coinbase) {
176 | | coinbase = block.coinbase;
177 | | }
178 | |
179 | | /// @notice Returns the block gas limit
180 | | function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
181 | | gaslimit = block.gaslimit;
182 | | }
183 | |
184 | | /// @notice Returns the block timestamp
185 | | function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
186 | | timestamp = block.timestamp;
187 | | }
188 | |
189 | | /// @notice Returns the (ETH) balance of a given address
190 | | function getEthBalance(address addr) public view returns (uint256 balance) {
191 | | balance = addr.balance;
192 | | }
193 | |
194 | | /// @notice Returns the block hash of the last block
195 | | function getLastBlockHash() public view returns (bytes32 blockHash) {
196 | | unchecked {
197 | | blockHash = blockhash(block.number - 1);
198 | | }
199 | | }
200 | |
201 | | /// @notice Gets the base fee of the given block
202 | | /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain
203 | | function getBasefee() public view returns (uint256 basefee) {
204 | | basefee = block.basefee;
205 | | }
206 | |
207 | | /// @notice Returns the chain id
208 | | function getChainId() public view returns (uint256 chainid) {
209 | | chainid = block.chainid;
210 | | }
211 | | }
212 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/ReferralStorage.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../referral/IReferralStorage.sol";
6 | | import "./Governable.sol";
7 | |
8 | | // @title ReferralStorage
9 | | // @dev Mock referral storage for testing and testnets
10 | * | contract ReferralStorage is IReferralStorage, Governable {
11 | | uint256 public constant BASIS_POINTS = 10000;
12 | |
13 | | // @dev mapping of affiliate to discount share for trader
14 | | // this overrides the default value in the affiliate's tier
15 | | mapping (address => uint256) public override referrerDiscountShares;
16 | | // @dev mapping of affiliate to tier
17 | | mapping (address => uint256) public override referrerTiers;
18 | | // @dev mapping tier level to tier values
19 | | mapping (uint256 => ReferralTier.Props) public override tiers;
20 | |
21 | | // @dev handlers for access control
22 | | mapping (address => bool) public isHandler;
23 | |
24 | | // @dev mapping of referral code to affiliate
25 | | mapping (bytes32 => address) public override codeOwners;
26 | | // @dev mapping of trader to referral code
27 | * | mapping (address => bytes32) public override traderReferralCodes;
28 | |
29 | | // @param handler the handler being set
30 | | // @param isActive whether the handler is being set to active or inactive
31 | | event SetHandler(address handler, bool isActive);
32 | | // @param account address of the trader
33 | | // @param code the referral code
34 | | event SetTraderReferralCode(address account, bytes32 code);
35 | | // @param tierId the tier level
36 | | // @param totalRebate the total rebate for the tier (affiliate reward + trader discount)
37 | | // @param discountShare the share of the totalRebate for traders
38 | | event SetTier(uint256 tierId, uint256 totalRebate, uint256 discountShare);
39 | | // @param referrer the affiliate
40 | | // @param tierId the new tier level
41 | | event SetReferrerTier(address referrer, uint256 tierId);
42 | | // @param referrer the affiliate
43 | | // @param discountShare the share of the totalRebate for traders
44 | | event SetReferrerDiscountShare(address referrer, uint256 discountShare);
45 | | // @param account the address of the affiliate
46 | | // @param code the referral code
47 | | event RegisterCode(address account, bytes32 code);
48 | | // @param account the previous owner of the referral code
49 | | // @param newAccount the new owner of the referral code
50 | | // @param code the referral code
51 | | event SetCodeOwner(address account, address newAccount, bytes32 code);
52 | | // @param newAccount the new owner of the referral code
53 | | // @param code the referral code
54 | | event GovSetCodeOwner(bytes32 code, address newAccount);
55 | |
56 | | modifier onlyHandler() {
57 | | require(isHandler[msg.sender], "ReferralStorage: forbidden");
58 | | _;
59 | | }
60 | |
61 | | // @dev set an address as a handler
62 | | // @param _handler address of the handler
63 | | // @param _isActive whether to set the handler as active or inactive
64 | | function setHandler(address _handler, bool _isActive) external onlyGov {
65 | | isHandler[_handler] = _isActive;
66 | | emit SetHandler(_handler, _isActive);
67 | | }
68 | |
69 | | // @dev set values for a tier
70 | | // @param _tierId the ID of the tier to set
71 | | // @param _totalRebate the total rebate
72 | | // @param _discountShare the discount share
73 | | function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external override onlyGov {
74 | | require(_totalRebate <= BASIS_POINTS, "ReferralStorage: invalid totalRebate");
75 | | require(_discountShare <= BASIS_POINTS, "ReferralStorage: invalid discountShare");
76 | |
77 | | ReferralTier.Props memory tier = tiers[_tierId];
78 | | tier.totalRebate = _totalRebate;
79 | | tier.discountShare = _discountShare;
80 | | tiers[_tierId] = tier;
81 | | emit SetTier(_tierId, _totalRebate, _discountShare);
82 | | }
83 | |
84 | | // @dev set the tier for an affiliate
85 | | // @param _referrer the address of the affiliate
86 | | // @param _tierId the tier to set to
87 | | function setReferrerTier(address _referrer, uint256 _tierId) external override onlyGov {
88 | | referrerTiers[_referrer] = _tierId;
89 | | emit SetReferrerTier(_referrer, _tierId);
90 | | }
91 | |
92 | | // @dev set the discount share for an affiliate
93 | | // @param _discountShare the discount share to set to
94 | | function setReferrerDiscountShare(uint256 _discountShare) external {
95 | | require(_discountShare <= BASIS_POINTS, "ReferralStorage: invalid discountShare");
96 | |
97 | | referrerDiscountShares[msg.sender] = _discountShare;
98 | | emit SetReferrerDiscountShare(msg.sender, _discountShare);
99 | | }
100 | |
101 | | // @dev set the referral code for a trader
102 | | // @param _account the address of the trader
103 | | // @param _code the referral code to set to
104 | | function setTraderReferralCode(address _account, bytes32 _code) external override onlyHandler {
105 | | _setTraderReferralCode(_account, _code);
106 | | }
107 | |
108 | | // @dev set the referral code for a trader
109 | | // @param _code the referral code to set to
110 | | function setTraderReferralCodeByUser(bytes32 _code) external {
111 | | _setTraderReferralCode(msg.sender, _code);
112 | | }
113 | |
114 | | // @dev register a referral code
115 | | // @param _code the referral code to register
116 | | function registerCode(bytes32 _code) external {
117 | | require(_code != bytes32(0), "ReferralStorage: invalid _code");
118 | | require(codeOwners[_code] == address(0), "ReferralStorage: code already exists");
119 | |
120 | | codeOwners[_code] = msg.sender;
121 | | emit RegisterCode(msg.sender, _code);
122 | | }
123 | |
124 | | // @dev for affiliates to set a new owner for a referral code they own
125 | | // @param _code the referral code
126 | | // @param _newAccount the new owner
127 | | function setCodeOwner(bytes32 _code, address _newAccount) external {
128 | | require(_code != bytes32(0), "ReferralStorage: invalid _code");
129 | |
130 | | address account = codeOwners[_code];
131 | | require(msg.sender == account, "ReferralStorage: forbidden");
132 | |
133 | | codeOwners[_code] = _newAccount;
134 | | emit SetCodeOwner(msg.sender, _newAccount, _code);
135 | | }
136 | |
137 | | // @dev set the owner of a referral code
138 | | // @param _code the referral code
139 | | // @param _newAccount the new owner
140 | | function govSetCodeOwner(bytes32 _code, address _newAccount) external override onlyGov {
141 | | require(_code != bytes32(0), "ReferralStorage: invalid _code");
142 | |
143 | | codeOwners[_code] = _newAccount;
144 | | emit GovSetCodeOwner(_code, _newAccount);
145 | | }
146 | |
147 | | // @dev get the referral info for a trader
148 | | // @param _account the address of the trader
149 | | function getTraderReferralInfo(address _account) external override view returns (bytes32, address) {
150 | | bytes32 code = traderReferralCodes[_account];
151 | | address referrer;
152 | | if (code != bytes32(0)) {
153 | | referrer = codeOwners[code];
154 | | }
155 | | return (code, referrer);
156 | | }
157 | |
158 | | // @dev set the referral code for a trader
159 | | // @param _account the address of the trader
160 | | // @param _code the referral code
161 | | function _setTraderReferralCode(address _account, bytes32 _code) private {
162 | | traderReferralCodes[_account] = _code;
163 | | emit SetTraderReferralCode(_account, _code);
164 | | }
165 | | }
166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/WNT.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6 | |
7 | | // @title WNT
8 | | // @dev similar implementation as WETH but since some networks
9 | | // might have a different native token we use WNT for a more general reference name
10 | * | contract WNT is ERC20 {
11 | | constructor() ERC20("Wrapped Native Token", "WNT") {}
12 | |
13 | | error TransferFailed(address account, uint256 amount);
14 | |
15 | | // @dev mint WNT by depositing the native token
16 | * | function deposit() external payable {
17 | * | _mint(msg.sender, msg.value);
18 | | }
19 | |
20 | | // @dev withdraw the native token by burning WNT
21 | | // @param amount the amount to withdraw
22 | * | function withdraw(uint256 amount) external {
23 | * | _burn(msg.sender, amount);
24 | * | (bool success, ) = msg.sender.call{ value: amount }("");
25 | * | if (!success) {
26 | | revert TransferFailed(msg.sender, amount);
27 | | }
28 | | }
29 | |
30 | | // @dev mint tokens to an account
31 | | // @param account the account to mint to
32 | | // @param amount the amount of tokens to mint
33 | | function mint(address account, uint256 amount) external {
34 | | _mint(account, amount);
35 | | }
36 | |
37 | | // @dev burn tokens from an account
38 | | // @param account the account to burn tokens for
39 | | // @param amount the amount of tokens to burn
40 | | function burn(address account, uint256 amount) external {
41 | | _burn(account, amount);
42 | | }
43 | | }
44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/nonce/NonceUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | |
8 | | // @title NonceUtils
9 | | // @dev Library to keep track of an incrementing nonce value
10 | * | library NonceUtils {
11 | | // @dev get the current nonce value
12 | | // @param dataStore DataStore
13 | | function getCurrentNonce(DataStore dataStore) internal view returns (uint256) {
14 | | return dataStore.getUint(Keys.NONCE);
15 | | }
16 | |
17 | | // @dev increment the current nonce value
18 | | // @param dataStore DataStore
19 | | // @return the new nonce value
20 | * | function incrementNonce(DataStore dataStore) internal returns (uint256) {
21 | * | return dataStore.incrementUint(Keys.NONCE, 1);
22 | | }
23 | |
24 | | // @dev convenience function to create a bytes32 hash using the next nonce
25 | | // it would be possible to use the nonce directly as an ID / key
26 | | // however, for positions the key is a bytes32 value based on a hash of
27 | | // the position values
28 | | // so bytes32 is used instead for a standard key type
29 | | // @param dataStore DataStore
30 | | // @return bytes32 hash using the next nonce value
31 | * | function getNextKey(DataStore dataStore) internal returns (bytes32) {
32 | * | uint256 nonce = incrementNonce(dataStore);
33 | * | bytes32 key = keccak256(abi.encode(address(dataStore), nonce));
34 | |
35 | * | return key;
36 | | }
37 | | }
38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkDataStreamProvider.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | | import "./IOracleProvider.sol";
8 | | import "./IChainlinkDataStreamVerifier.sol";
9 | | import "../utils/Precision.sol";
10 | | import "../chain/Chain.sol";
11 | |
12 | * | contract ChainlinkDataStreamProvider is IOracleProvider {
13 | |
14 | | DataStore public immutable dataStore;
15 | | address public immutable oracle;
16 | | IChainlinkDataStreamVerifier public immutable verifier;
17 | |
18 | | // bid: min price, highest buy price
19 | | // ask: max price, lowest sell price
20 | | struct Report {
21 | | bytes32 feedId; // The feed ID the report has data for
22 | | uint32 validFromTimestamp; // Earliest timestamp for which price is applicable
23 | | uint32 observationsTimestamp; // Latest timestamp for which price is applicable
24 | | uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (WETH/ETH)
25 | | uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK
26 | | uint32 expiresAt; // Latest timestamp where the report can be verified onchain
27 | | int192 price; // DON consensus median price, carried to 8 decimal places
28 | | int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation
29 | | int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation
30 | | }
31 | |
32 | | modifier onlyOracle() {
33 | | if (msg.sender != oracle) {
34 | | revert Errors.Unauthorized(msg.sender, "Oracle");
35 | | }
36 | | _;
37 | | }
38 | |
39 | | constructor(
40 | | DataStore _dataStore,
41 | | address _oracle,
42 | | IChainlinkDataStreamVerifier _verifier
43 | | ) {
44 | | dataStore = _dataStore;
45 | | oracle = _oracle;
46 | | verifier = _verifier;
47 | | }
48 | |
49 | | function getOraclePrice(
50 | | address token,
51 | | bytes memory data
52 | | ) external onlyOracle returns (OracleUtils.ValidatedPrice memory) {
53 | |
54 | | bytes32 feedId = dataStore.getBytes32(Keys.dataStreamIdKey(token));
55 | | if (feedId == bytes32(0)) {
56 | | revert Errors.EmptyDataStreamFeedId(token);
57 | | }
58 | |
59 | | bytes memory payloadParameter = _getPayloadParameter();
60 | | bytes memory verifierResponse = verifier.verify(data, payloadParameter);
61 | |
62 | | Report memory report = abi.decode(verifierResponse, (Report));
63 | |
64 | | if (feedId != report.feedId) {
65 | | revert Errors.InvalidDataStreamFeedId(token, report.feedId, feedId);
66 | | }
67 | |
68 | | if (report.bid <= 0 || report.ask <= 0) {
69 | | revert Errors.InvalidDataStreamPrices(token, report.bid, report.ask);
70 | | }
71 | |
72 | | if (report.bid > report.ask) {
73 | | revert Errors.InvalidDataStreamBidAsk(token, report.bid, report.ask);
74 | | }
75 | |
76 | | uint256 precision = _getDataStreamMultiplier(token);
77 | | uint256 adjustedBidPrice = Precision.mulDiv(uint256(uint192(report.bid)), precision, Precision.FLOAT_PRECISION);
78 | | uint256 adjustedAskPrice = Precision.mulDiv(uint256(uint192(report.ask)), precision, Precision.FLOAT_PRECISION);
79 | |
80 | | return OracleUtils.ValidatedPrice({
81 | | token: token,
82 | | min: adjustedBidPrice,
83 | | max: adjustedAskPrice,
84 | | timestamp: report.observationsTimestamp,
85 | | provider: address(this)
86 | | });
87 | | }
88 | |
89 | | function _getDataStreamMultiplier(address token) internal view returns (uint256) {
90 | | uint256 multiplier = dataStore.getUint(Keys.dataStreamMultiplierKey(token));
91 | |
92 | | if (multiplier == 0) {
93 | | revert Errors.EmptyDataStreamMultiplier(token);
94 | | }
95 | |
96 | | return multiplier;
97 | | }
98 | |
99 | | function _getPayloadParameter() internal view returns (bytes memory) {
100 | | // LINK token address
101 | | address feeToken = dataStore.getAddress(Keys.CHAINLINK_PAYMENT_TOKEN);
102 | |
103 | | if (feeToken == address(0)) {
104 | | revert Errors.EmptyChainlinkPaymentToken();
105 | | }
106 | |
107 | | return abi.encode(feeToken);
108 | | }
109 | | }
110 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkPriceFeedProvider.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | | import "./IOracleProvider.sol";
8 | | import "./ChainlinkPriceFeedUtils.sol";
9 | |
10 | * | contract ChainlinkPriceFeedProvider is IOracleProvider {
11 | | DataStore public immutable dataStore;
12 | |
13 | | constructor(DataStore _dataStore) {
14 | | dataStore = _dataStore;
15 | | }
16 | |
17 | | // @dev the timestamp returned is based on the current blockchain timestamp
18 | | // this is because Chainlink on-chain price feeds have a lower update frequency
19 | | // if a Chainlink on-chain price feed is used, it is assumed that the feed
20 | | // is sufficiently updated for the intended usage
21 | | //
22 | | // if an on-chain Chainlink price is used together with other price feeds
23 | | // and if the timestamp of the other price feeds are older, this could cause
24 | | // a MaxTimestampRangeExceeded error
25 | | // if this occurs, the MAX_TIMESTAMP_RANGE value may need to be increased
26 | | function getOraclePrice(
27 | | address token,
28 | | bytes memory /* data */
29 | | ) external view returns (OracleUtils.ValidatedPrice memory) {
30 | | (bool hasPriceFeed, uint256 price) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);
31 | |
32 | | if (!hasPriceFeed) {
33 | | revert Errors.EmptyChainlinkPriceFeed(token);
34 | | }
35 | |
36 | | uint256 stablePrice = dataStore.getUint(Keys.stablePriceKey(token));
37 | |
38 | | Price.Props memory priceProps;
39 | |
40 | | if (stablePrice > 0) {
41 | | priceProps = Price.Props(
42 | | price < stablePrice ? price : stablePrice,
43 | | price < stablePrice ? stablePrice : price
44 | | );
45 | | } else {
46 | | priceProps = Price.Props(
47 | | price,
48 | | price
49 | | );
50 | | }
51 | |
52 | | return OracleUtils.ValidatedPrice({
53 | | token: token,
54 | | min: priceProps.min,
55 | | max: priceProps.max,
56 | | timestamp: Chain.currentTimestamp(),
57 | | provider: address(this)
58 | | });
59 | | }
60 | | }
61 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkPriceFeedUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../chain/Chain.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../data/Keys.sol";
8 | | import "../utils/Precision.sol";
9 | |
10 | | import "./IPriceFeed.sol";
11 | |
12 | | // @title ChainlinkPriceFeedProviderUtils
13 | | // @dev Library for Chainlink price feed
14 | * | library ChainlinkPriceFeedUtils {
15 | | // there is a small risk of stale pricing due to latency in price updates or if the chain is down
16 | | // this is meant to be for temporary use until low latency price feeds are supported for all tokens
17 | | function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {
18 | | address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));
19 | | if (priceFeedAddress == address(0)) {
20 | | return (false, 0);
21 | | }
22 | |
23 | | IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);
24 | |
25 | | (
26 | | /* uint80 roundID */,
27 | | int256 _price,
28 | | /* uint256 startedAt */,
29 | | uint256 timestamp,
30 | | /* uint80 answeredInRound */
31 | | ) = priceFeed.latestRoundData();
32 | |
33 | | if (_price <= 0) {
34 | | revert Errors.InvalidFeedPrice(token, _price);
35 | | }
36 | |
37 | | uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));
38 | | if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {
39 | | revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);
40 | | }
41 | |
42 | | uint256 price = SafeCast.toUint256(_price);
43 | | uint256 precision = getPriceFeedMultiplier(dataStore, token);
44 | |
45 | | uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);
46 | |
47 | | return (true, adjustedPrice);
48 | | }
49 | |
50 | | // @dev get the multiplier value to convert the internal price feed price to the price of 1 unit of the token
51 | | // represented with 30 decimals
52 | | // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of
53 | | // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)
54 | | // if the internal price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8)
55 | | // in this case the priceFeedMultiplier should be 10 ^ 46
56 | | // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24)
57 | | // formula for decimals for price feed multiplier: 60 - (internal price feed decimals) - (token decimals)
58 | | //
59 | | // @param dataStore DataStore
60 | | // @param token the token to get the price feed multiplier for
61 | | // @return the price feed multipler
62 | | function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {
63 | | uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));
64 | |
65 | | if (multiplier == 0) {
66 | | revert Errors.EmptyChainlinkPriceFeedMultiplier(token);
67 | | }
68 | |
69 | | return multiplier;
70 | | }
71 | | }
72 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/GmOracleProvider.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
7 | |
8 | | import "../role/RoleModule.sol";
9 | |
10 | | import "./OracleStore.sol";
11 | | import "./OracleUtils.sol";
12 | | import "./IPriceFeed.sol";
13 | | import "../price/Price.sol";
14 | | import "./GmOracleUtils.sol";
15 | | import "./IOracleProvider.sol";
16 | |
17 | | import "../chain/Chain.sol";
18 | | import "../data/Keys.sol";
19 | | import "../data/DataStore.sol";
20 | | import "../event/EventEmitter.sol";
21 | | import "../event/EventUtils.sol";
22 | |
23 | | import "../utils/Bits.sol";
24 | | import "../utils/Array.sol";
25 | | import "../utils/Precision.sol";
26 | | import "../utils/Cast.sol";
27 | | import "../utils/Uint256Mask.sol";
28 | |
29 | | // @title Oracle
30 | | // @dev Contract to validate and store signed values
31 | | // Some calculations e.g. calculating the size in tokens for a position
32 | | // may not work with zero / negative prices
33 | | // as a result, zero / negative prices are considered empty / invalid
34 | | // A market may need to be manually settled in this case
35 | * | contract GmOracleProvider is RoleModule, IOracleProvider {
36 | | using Price for Price.Props;
37 | | using Uint256Mask for Uint256Mask.Mask;
38 | |
39 | | uint256 public constant SIGNER_INDEX_LENGTH = 16;
40 | | // subtract 1 as the first slot is used to store number of signers
41 | | uint256 public constant MAX_SIGNERS = 256 / SIGNER_INDEX_LENGTH - 1;
42 | | // signer indexes are recorded in a signerIndexFlags uint256 value to check for uniqueness
43 | | uint256 public constant MAX_SIGNER_INDEX = 256;
44 | |
45 | | DataStore public immutable dataStore;
46 | | OracleStore public immutable oracleStore;
47 | |
48 | | constructor(
49 | | RoleStore _roleStore,
50 | | DataStore _dataStore,
51 | | OracleStore _oracleStore
52 | | ) RoleModule(_roleStore) {
53 | | dataStore = _dataStore;
54 | | oracleStore = _oracleStore;
55 | | }
56 | |
57 | | // @dev Oracle prices are signed as a value together with a precision, this allows
58 | | // prices to be compacted as uint32 values.
59 | | //
60 | | // The signed prices represent the price of one unit of the token using a value
61 | | // with 30 decimals of precision.
62 | | //
63 | | // Representing the prices in this way allows for conversions between token amounts
64 | | // and fiat values to be simplified, e.g. to calculate the fiat value of a given
65 | | // number of tokens the calculation would just be: `token amount * oracle price`,
66 | | // to calculate the token amount for a fiat value it would be: `fiat value / oracle price`.
67 | | //
68 | | // The trade-off of this simplicity in calculation is that tokens with a small USD
69 | | // price and a lot of decimals may have precision issues it is also possible that
70 | | // a token's price changes significantly and results in requiring higher precision.
71 | | //
72 | | // ## Example 1
73 | | //
74 | | // The price of ETH is 5000, and ETH has 18 decimals.
75 | | //
76 | | // The price of one unit of ETH is `5000 / (10 ^ 18), 5 * (10 ^ -15)`.
77 | | //
78 | | // To handle the decimals, multiply the value by `(10 ^ 30)`.
79 | | //
80 | | // Price would be stored as `5000 / (10 ^ 18) * (10 ^ 30) => 5000 * (10 ^ 12)`.
81 | | //
82 | | // For gas optimization, these prices are sent to the oracle in the form of a uint8
83 | | // decimal multiplier value and uint32 price value.
84 | | //
85 | | // If the decimal multiplier value is set to 8, the uint32 value would be `5000 * (10 ^ 12) / (10 ^ 8) => 5000 * (10 ^ 4)`.
86 | | //
87 | | // With this config, ETH prices can have a maximum value of `(2 ^ 32) / (10 ^ 4) => 4,294,967,296 / (10 ^ 4) => 429,496.7296` with 4 decimals of precision.
88 | | //
89 | | // ## Example 2
90 | | //
91 | | // The price of BTC is 60,000, and BTC has 8 decimals.
92 | | //
93 | | // The price of one unit of BTC is `60,000 / (10 ^ 8), 6 * (10 ^ -4)`.
94 | | //
95 | | // Price would be stored as `60,000 / (10 ^ 8) * (10 ^ 30) => 6 * (10 ^ 26) => 60,000 * (10 ^ 22)`.
96 | | //
97 | | // BTC prices maximum value: `(2 ^ 32) / (10 ^ 2) => 4,294,967,296 / (10 ^ 2) => 42,949,672.96`.
98 | | //
99 | | // Decimals of precision: 2.
100 | | //
101 | | // ## Example 3
102 | | //
103 | | // The price of USDC is 1, and USDC has 6 decimals.
104 | | //
105 | | // The price of one unit of USDC is `1 / (10 ^ 6), 1 * (10 ^ -6)`.
106 | | //
107 | | // Price would be stored as `1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)`.
108 | | //
109 | | // USDC prices maximum value: `(2 ^ 64) / (10 ^ 6) => 4,294,967,296 / (10 ^ 6) => 4294.967296`.
110 | | //
111 | | // Decimals of precision: 6.
112 | | //
113 | | // ## Example 4
114 | | //
115 | | // The price of DG is 0.00000001, and DG has 18 decimals.
116 | | //
117 | | // The price of one unit of DG is `0.00000001 / (10 ^ 18), 1 * (10 ^ -26)`.
118 | | //
119 | | // Price would be stored as `1 * (10 ^ -26) * (10 ^ 30) => 1 * (10 ^ 3)`.
120 | | //
121 | | // DG prices maximum value: `(2 ^ 64) / (10 ^ 11) => 4,294,967,296 / (10 ^ 11) => 0.04294967296`.
122 | | //
123 | | // Decimals of precision: 11.
124 | | //
125 | | // ## Decimal Multiplier
126 | | //
127 | | // The formula to calculate what the decimal multiplier value should be set to:
128 | | //
129 | | // Decimals: 30 - (token decimals) - (number of decimals desired for precision)
130 | | //
131 | | // - ETH: 30 - 18 - 4 => 8
132 | | // - BTC: 30 - 8 - 2 => 20
133 | | // - USDC: 30 - 6 - 6 => 18
134 | | // - DG: 30 - 18 - 11 => 1
135 | | function getOraclePrice(
136 | | address token,
137 | | bytes memory data
138 | | ) external view returns (OracleUtils.ValidatedPrice memory) {
139 | | GmOracleUtils.Report memory report = abi.decode(data, (GmOracleUtils.Report));
140 | | address[] memory signers = _getSigners(report.signerInfo);
141 | |
142 | | if (report.minOracleBlockNumber > report.maxOracleBlockNumber) {
143 | | revert Errors.GmInvalidMinMaxBlockNumber(report.minOracleBlockNumber, report.maxOracleBlockNumber);
144 | | }
145 | |
146 | | if (report.maxOracleBlockNumber >= Chain.currentBlockNumber()) {
147 | | revert Errors.GmInvalidBlockNumber(report.maxOracleBlockNumber, Chain.currentBlockNumber());
148 | | }
149 | |
150 | | bytes32 tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(token));
151 | |
152 | | for (uint256 i = 0; i < signers.length; i++) {
153 | | if (i == 0) { continue; }
154 | |
155 | | // validate that minPrices are sorted in ascending order
156 | | if (report.minPrices[i - 1] > report.minPrices[i]) {
157 | | revert Errors.GmMinPricesNotSorted(token, report.minPrices[i], report.minPrices[i - 1]);
158 | | }
159 | |
160 | | // validate that maxPrices are sorted in ascending order
161 | | if (report.maxPrices[i - 1] > report.maxPrices[i]) {
162 | | revert Errors.GmMaxPricesNotSorted(token, report.maxPrices[i], report.maxPrices[i - 1]);
163 | | }
164 | | }
165 | |
166 | | bytes32 salt = _getSalt();
167 | |
168 | | for (uint256 i = 0; i < signers.length; i++) {
169 | | uint256 minPrice = report.minPrices[i];
170 | | uint256 maxPrice = report.maxPrices[i];
171 | |
172 | | if (minPrice > maxPrice) {
173 | | revert Errors.InvalidGmSignerMinMaxPrice(minPrice, maxPrice);
174 | | }
175 | |
176 | | GmOracleUtils.validateSigner(
177 | | salt,
178 | | report,
179 | | token,
180 | | minPrice,
181 | | maxPrice,
182 | | tokenOracleType,
183 | | report.signatures[i],
184 | | signers[i]
185 | | );
186 | | }
187 | |
188 | | uint256 medianMinPrice = Array.getMedian(report.minPrices) * (10 ** report.precision);
189 | | uint256 medianMaxPrice = Array.getMedian(report.maxPrices) * (10 ** report.precision);
190 | |
191 | | if (medianMinPrice == 0 || medianMaxPrice == 0) {
192 | | revert Errors.InvalidGmOraclePrice(token);
193 | | }
194 | |
195 | | if (medianMinPrice > medianMaxPrice) {
196 | | revert Errors.InvalidGmMedianMinMaxPrice(medianMinPrice, medianMaxPrice);
197 | | }
198 | |
199 | | return OracleUtils.ValidatedPrice({
200 | | token: token,
201 | | min: medianMinPrice,
202 | | max: medianMaxPrice,
203 | | timestamp: report.oracleTimestamp,
204 | | provider: address(this)
205 | | });
206 | | }
207 | |
208 | | function _getSigners(
209 | | uint256 signerInfo
210 | | ) internal view returns (address[] memory) {
211 | | // first 16 bits of signer info contains the number of signers
212 | | address[] memory signers = new address[](signerInfo & Bits.BITMASK_16);
213 | |
214 | | if (signers.length < dataStore.getUint(Keys.MIN_ORACLE_SIGNERS)) {
215 | | revert Errors.GmMinOracleSigners(signers.length, dataStore.getUint(Keys.MIN_ORACLE_SIGNERS));
216 | | }
217 | |
218 | | if (signers.length > MAX_SIGNERS) {
219 | | revert Errors.GmMaxOracleSigners(signers.length, MAX_SIGNERS);
220 | | }
221 | |
222 | | Uint256Mask.Mask memory signerIndexMask;
223 | |
224 | | for (uint256 i; i < signers.length; i++) {
225 | | uint256 signerIndex = signerInfo >> (16 + 16 * i) & Bits.BITMASK_16;
226 | |
227 | | if (signerIndex >= MAX_SIGNER_INDEX) {
228 | | revert Errors.GmMaxSignerIndex(signerIndex, MAX_SIGNER_INDEX);
229 | | }
230 | |
231 | | signerIndexMask.validateUniqueAndSetIndex(signerIndex, "signerIndex");
232 | |
233 | | signers[i] = oracleStore.getSigner(signerIndex);
234 | |
235 | | if (signers[i] == address(0)) {
236 | | revert Errors.GmEmptySigner(signerIndex);
237 | | }
238 | | }
239 | |
240 | | return signers;
241 | | }
242 | |
243 | | // it might be possible for the block.chainid to change due to a fork or similar
244 | | // for this reason, this salt is not cached
245 | | function _getSalt() internal view returns (bytes32) {
246 | | return keccak256(abi.encode(block.chainid, "xget-oracle-v1"));
247 | | }
248 | | }
249 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/GmOracleUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
6 | | import "../error/Errors.sol";
7 | |
8 | | // @title GmOracleUtils
9 | | // @dev Library for GmOracle functions
10 | * | library GmOracleUtils {
11 | | struct Report {
12 | | address token;
13 | | uint256 signerInfo;
14 | | uint256 precision;
15 | | uint256 minOracleBlockNumber;
16 | | uint256 maxOracleBlockNumber;
17 | | uint256 oracleTimestamp;
18 | | bytes32 blockHash;
19 | | uint256[] minPrices;
20 | | uint256[] maxPrices;
21 | | bytes[] signatures;
22 | | }
23 | |
24 | | // @dev validate the signer of a price
25 | | // before calling this function, the expectedSigner should be validated to
26 | | // ensure that it is not the zero address
27 | | // @param report the oracle Report data
28 | | // @param token the token used for the signed message hash
29 | | // @param minPrice the min price used for the signed message hash
30 | | // @param maxPrice the max price used for the signed message hash
31 | | // @param tokenOracleType the token oracle type used for the signed message hash
32 | | // @param signature the signer's signature
33 | | // @param expectedSigner the address of the expected signer
34 | | function validateSigner(
35 | | bytes32 salt,
36 | | Report memory report,
37 | | address token,
38 | | uint256 minPrice,
39 | | uint256 maxPrice,
40 | | bytes32 tokenOracleType,
41 | | bytes memory signature,
42 | | address expectedSigner
43 | | ) internal pure {
44 | | bytes32 digest = ECDSA.toEthSignedMessageHash(
45 | | keccak256(abi.encode(
46 | | salt,
47 | | report.minOracleBlockNumber,
48 | | report.maxOracleBlockNumber,
49 | | report.oracleTimestamp,
50 | | report.blockHash,
51 | | token,
52 | | tokenOracleType,
53 | | 10 ** report.precision,
54 | | minPrice,
55 | | maxPrice
56 | | ))
57 | | );
58 | |
59 | | address recoveredSigner = ECDSA.recover(digest, signature);
60 | | if (recoveredSigner != expectedSigner) {
61 | | revert Errors.InvalidGmSignature(recoveredSigner, expectedSigner);
62 | | }
63 | | }
64 | | }
65 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IChainlinkDataStreamVerifier.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | interface IChainlinkDataStreamVerifier {
6 | | /**
7 | | * @notice Verifies that the data encoded has been signed
8 | | * correctly by routing to the correct verifier, and bills the user if applicable.
9 | | * @param payload The encoded data to be verified, including the signed
10 | | * report.
11 | | * @param parameterPayload fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address
12 | | * @return verifierResponse The encoded report from the verifier.
13 | | */
14 | | function verify(
15 | | bytes calldata payload,
16 | | bytes calldata parameterPayload
17 | | ) external payable returns (bytes memory verifierResponse);
18 | | }
19 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IOracleProvider.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./OracleUtils.sol";
6 | |
7 | | // @title IOracleProvider
8 | | // @dev Interface for an oracle provider
9 | | interface IOracleProvider {
10 | | function getOraclePrice(
11 | | address token,
12 | | bytes memory data
13 | | ) external returns (OracleUtils.ValidatedPrice memory);
14 | | }
15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IPriceFeed.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title IPriceFeed
6 | | // @dev Interface for a price feed
7 | | interface IPriceFeed {
8 | | function latestRoundData() external view returns (
9 | | uint80 roundId,
10 | | int256 answer,
11 | | uint256 startedAt,
12 | | uint256 updatedAt,
13 | | uint80 answeredInRound
14 | | );
15 | | }
16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/Oracle.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
7 | | import { AggregatorV2V3Interface } from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
8 | |
9 | | import "../role/RoleModule.sol";
10 | |
11 | | import "./OracleStore.sol";
12 | | import "./OracleUtils.sol";
13 | | import "./IPriceFeed.sol";
14 | | import "./IOracleProvider.sol";
15 | | import "./ChainlinkPriceFeedUtils.sol";
16 | | import "../price/Price.sol";
17 | |
18 | | import "../chain/Chain.sol";
19 | | import "../data/DataStore.sol";
20 | | import "../data/Keys.sol";
21 | | import "../event/EventEmitter.sol";
22 | | import "../event/EventUtils.sol";
23 | |
24 | | import "../utils/Bits.sol";
25 | | import "../utils/Array.sol";
26 | | import "../utils/Precision.sol";
27 | | import "../utils/Cast.sol";
28 | | import "../utils/Uint256Mask.sol";
29 | |
30 | | // @title Oracle
31 | | // @dev Contract to validate and store signed values
32 | | // Some calculations e.g. calculating the size in tokens for a position
33 | | // may not work with zero / negative prices
34 | | // as a result, zero / negative prices are considered empty / invalid
35 | | // A market may need to be manually settled in this case
36 | * | contract Oracle is RoleModule {
37 | | using EnumerableSet for EnumerableSet.AddressSet;
38 | | using EnumerableValues for EnumerableSet.AddressSet;
39 | | using Price for Price.Props;
40 | | using Uint256Mask for Uint256Mask.Mask;
41 | |
42 | | using EventUtils for EventUtils.AddressItems;
43 | | using EventUtils for EventUtils.UintItems;
44 | | using EventUtils for EventUtils.IntItems;
45 | | using EventUtils for EventUtils.BoolItems;
46 | | using EventUtils for EventUtils.Bytes32Items;
47 | | using EventUtils for EventUtils.BytesItems;
48 | | using EventUtils for EventUtils.StringItems;
49 | |
50 | | DataStore public immutable dataStore;
51 | | EventEmitter public immutable eventEmitter;
52 | | AggregatorV2V3Interface public immutable sequencerUptimeFeed;
53 | |
54 | | // tokensWithPrices stores the tokens with prices that have been set
55 | | // this is used in clearAllPrices to help ensure that all token prices
56 | | // set in setPrices are cleared after use
57 | | EnumerableSet.AddressSet internal tokensWithPrices;
58 | | mapping(address => Price.Props) public primaryPrices;
59 | |
60 | * | uint256 public minTimestamp;
61 | * | uint256 public maxTimestamp;
62 | |
63 | | constructor(
64 | | RoleStore _roleStore,
65 | | DataStore _dataStore,
66 | | EventEmitter _eventEmitter,
67 | | AggregatorV2V3Interface _sequencerUptimeFeed
68 | | ) RoleModule(_roleStore) {
69 | | dataStore = _dataStore;
70 | | eventEmitter = _eventEmitter;
71 | | sequencerUptimeFeed = _sequencerUptimeFeed;
72 | | }
73 | |
74 | | // this can be used to help ensure that on-chain prices are updated
75 | | // before actions dependent on those on-chain prices are allowed
76 | | // additionally, this can also be used to provide a grace period for
77 | | // users to top up collateral before liquidations occur
78 | * | function validateSequencerUp() external view {
79 | * | if (address(sequencerUptimeFeed) == address(0)) {
80 | * | return;
81 | | }
82 | |
83 | | (
84 | | /*uint80 roundID*/,
85 | | int256 answer,
86 | | uint256 startedAt,
87 | | /*uint256 updatedAt*/,
88 | | /*uint80 answeredInRound*/
89 | | ) = sequencerUptimeFeed.latestRoundData();
90 | |
91 | | // Answer == 0: Sequencer is up
92 | | // Answer == 1: Sequencer is down
93 | | bool isSequencerUp = answer == 0;
94 | | if (!isSequencerUp) {
95 | | revert Errors.SequencerDown();
96 | | }
97 | |
98 | | uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);
99 | |
100 | | // Make sure the grace duration has passed after the
101 | | // sequencer is back up.
102 | | uint256 timeSinceUp = block.timestamp - startedAt;
103 | | if (timeSinceUp <= sequencerGraceDuration) {
104 | | revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);
105 | | }
106 | | }
107 | |
108 | * | function setPrices(
109 | | OracleUtils.SetPricesParams memory params
110 | * | ) external onlyController {
111 | * | OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);
112 | |
113 | * | _setPrices(prices);
114 | | }
115 | |
116 | * | function setPricesForAtomicAction(
117 | | OracleUtils.SetPricesParams memory params
118 | * | ) external onlyController {
119 | * | OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);
120 | |
121 | * | _setPrices(prices);
122 | | }
123 | |
124 | | // @dev set the primary price
125 | | // @param token the token to set the price for
126 | | // @param price the price value to set to
127 | | function setPrimaryPrice(address token, Price.Props memory price) external onlyController {
128 | | _setPrimaryPrice(token, price);
129 | | }
130 | |
131 | | function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {
132 | | minTimestamp = _minTimestamp;
133 | | maxTimestamp = _maxTimestamp;
134 | | }
135 | |
136 | | // @dev clear all prices
137 | * | function clearAllPrices() external onlyController {
138 | * | uint256 length = tokensWithPrices.length();
139 | * | for (uint256 i; i < length; i++) {
140 | * | address token = tokensWithPrices.at(0);
141 | * | _removePrimaryPrice(token);
142 | | }
143 | |
144 | * | minTimestamp = 0;
145 | * | maxTimestamp = 0;
146 | | }
147 | |
148 | | // @dev get the length of tokensWithPrices
149 | | // @return the length of tokensWithPrices
150 | | function getTokensWithPricesCount() external view returns (uint256) {
151 | | return tokensWithPrices.length();
152 | | }
153 | |
154 | | // @dev get the tokens of tokensWithPrices for the specified indexes
155 | | // @param start the start index, the value for this index will be included
156 | | // @param end the end index, the value for this index will not be included
157 | | // @return the tokens of tokensWithPrices for the specified indexes
158 | | function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {
159 | | return tokensWithPrices.valuesAt(start, end);
160 | | }
161 | |
162 | | // @dev get the primary price of a token
163 | | // @param token the token to get the price for
164 | | // @return the primary price of a token
165 | * | function getPrimaryPrice(address token) external view returns (Price.Props memory) {
166 | * | if (token == address(0)) { return Price.Props(0, 0); }
167 | |
168 | * | Price.Props memory price = primaryPrices[token];
169 | * | if (price.isEmpty()) {
170 | | revert Errors.EmptyPrimaryPrice(token);
171 | | }
172 | |
173 | * | return price;
174 | | }
175 | |
176 | | function validatePrices(
177 | | OracleUtils.SetPricesParams memory params,
178 | | bool forAtomicAction
179 | | ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {
180 | | return _validatePrices(params, forAtomicAction);
181 | | }
182 | |
183 | | // @dev validate and set prices
184 | | // @param params OracleUtils.SetPricesParams
185 | * | function _setPrices(
186 | | OracleUtils.ValidatedPrice[] memory prices
187 | * | ) internal returns (OracleUtils.ValidatedPrice[] memory) {
188 | * | if (tokensWithPrices.length() != 0) {
189 | | revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());
190 | | }
191 | |
192 | * | if (prices.length == 0) {
193 | | revert Errors.EmptyValidatedPrices();
194 | | }
195 | |
196 | * | uint256 _minTimestamp = prices[0].timestamp;
197 | * | uint256 _maxTimestamp = prices[0].timestamp;
198 | |
199 | * | for (uint256 i; i < prices.length; i++) {
200 | * | OracleUtils.ValidatedPrice memory validatedPrice = prices[i];
201 | |
202 | * | _setPrimaryPrice(validatedPrice.token, Price.Props(
203 | * | validatedPrice.min,
204 | * | validatedPrice.max
205 | | ));
206 | |
207 | * | if (validatedPrice.timestamp < _minTimestamp) {
208 | | _minTimestamp = validatedPrice.timestamp;
209 | | }
210 | |
211 | * | if (validatedPrice.timestamp > _maxTimestamp) {
212 | | _maxTimestamp = validatedPrice.timestamp;
213 | | }
214 | |
215 | * | _emitOraclePriceUpdated(
216 | * | validatedPrice.token,
217 | * | validatedPrice.min,
218 | * | validatedPrice.max,
219 | * | validatedPrice.timestamp,
220 | * | validatedPrice.provider
221 | | );
222 | | }
223 | |
224 | * | uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);
225 | * | if (_maxTimestamp - _minTimestamp > maxRange) {
226 | | revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);
227 | | }
228 | |
229 | * | minTimestamp = _minTimestamp;
230 | * | maxTimestamp = _maxTimestamp;
231 | |
232 | * | return prices;
233 | | }
234 | |
235 | * | function _validatePrices(
236 | | OracleUtils.SetPricesParams memory params,
237 | | bool forAtomicAction
238 | * | ) internal returns (OracleUtils.ValidatedPrice[] memory) {
239 | * | if (params.tokens.length != params.providers.length) {
240 | | revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);
241 | | }
242 | |
243 | * | if (params.tokens.length != params.data.length) {
244 | | revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);
245 | | }
246 | |
247 | * | OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);
248 | |
249 | * | uint256 maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);
250 | * | uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);
251 | |
252 | * | for (uint256 i; i < params.tokens.length; i++) {
253 | * | address provider = params.providers[i];
254 | |
255 | * | if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(provider))) {
256 | | revert Errors.InvalidOracleProvider(provider);
257 | | }
258 | |
259 | * | address token = params.tokens[i];
260 | |
261 | * | bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(provider));
262 | |
263 | | // if the action is atomic then only validate that the provider is an
264 | | // atomic provider
265 | | // else, validate that the provider matches the oracleProviderForToken
266 | | //
267 | | // since for atomic actions, any atomic provider can be used, it is
268 | | // recommended that only one atomic provider is configured per token
269 | | // otherwise there is a risk that if there is a difference in pricing
270 | | // between atomic oracle providers for a token, a user could use that
271 | | // to gain a profit by alternating actions between the two atomic
272 | | // providers
273 | * | if (forAtomicAction) {
274 | * | if (!isAtomicProvider) {
275 | | revert Errors.NonAtomicOracleProvider(provider);
276 | | }
277 | * | } else {
278 | * | address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(token));
279 | * | if (provider != expectedProvider) {
280 | | revert Errors.InvalidOracleProviderForToken(provider, expectedProvider);
281 | | }
282 | | }
283 | |
284 | * | bytes memory data = params.data[i];
285 | |
286 | * | OracleUtils.ValidatedPrice memory validatedPrice = IOracleProvider(provider).getOraclePrice(
287 | * | token,
288 | * | data
289 | | );
290 | |
291 | | // for atomic providers, the timestamp will be the current block's timestamp
292 | | // the timestamp should not be adjusted
293 | * | if (!isAtomicProvider) {
294 | | uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(provider, token));
295 | | validatedPrice.timestamp -= timestampAdjustment;
296 | | }
297 | |
298 | * | if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {
299 | | revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());
300 | | }
301 | |
302 | | // for atomic providers, assume that Chainlink would be the main provider
303 | | // so it would be redundant to re-fetch the Chainlink price for validation
304 | * | if (!isAtomicProvider) {
305 | | (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);
306 | |
307 | | if (hasRefPrice) {
308 | | _validateRefPrice(
309 | | token,
310 | | validatedPrice.min,
311 | | refPrice,
312 | | maxRefPriceDeviationFactor
313 | | );
314 | |
315 | | _validateRefPrice(
316 | | token,
317 | | validatedPrice.max,
318 | | refPrice,
319 | | maxRefPriceDeviationFactor
320 | | );
321 | | }
322 | | }
323 | |
324 | * | prices[i] = validatedPrice;
325 | | }
326 | |
327 | * | return prices;
328 | | }
329 | |
330 | | function _validateRefPrice(
331 | | address token,
332 | | uint256 price,
333 | | uint256 refPrice,
334 | | uint256 maxRefPriceDeviationFactor
335 | | ) internal pure {
336 | | uint256 diff = Calc.diff(price, refPrice);
337 | | uint256 diffFactor = Precision.toFactor(diff, refPrice);
338 | |
339 | | if (diffFactor > maxRefPriceDeviationFactor) {
340 | | revert Errors.MaxRefPriceDeviationExceeded(
341 | | token,
342 | | price,
343 | | refPrice,
344 | | maxRefPriceDeviationFactor
345 | | );
346 | | }
347 | | }
348 | |
349 | * | function _setPrimaryPrice(address token, Price.Props memory price) internal {
350 | * | if (price.min > price.max) {
351 | | revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);
352 | | }
353 | |
354 | * | Price.Props memory existingPrice = primaryPrices[token];
355 | |
356 | * | if (!existingPrice.isEmpty()) {
357 | | revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);
358 | | }
359 | |
360 | * | primaryPrices[token] = price;
361 | * | tokensWithPrices.add(token);
362 | | }
363 | |
364 | * | function _removePrimaryPrice(address token) internal {
365 | * | delete primaryPrices[token];
366 | * | tokensWithPrices.remove(token);
367 | | }
368 | |
369 | * | function _emitOraclePriceUpdated(
370 | | address token,
371 | | uint256 minPrice,
372 | | uint256 maxPrice,
373 | | uint256 timestamp,
374 | | address provider
375 | * | ) internal {
376 | * | EventUtils.EventLogData memory eventData;
377 | |
378 | * | eventData.addressItems.initItems(2);
379 | * | eventData.addressItems.setItem(0, "token", token);
380 | * | eventData.addressItems.setItem(1, "provider", provider);
381 | |
382 | * | eventData.uintItems.initItems(3);
383 | * | eventData.uintItems.setItem(0, "minPrice", minPrice);
384 | * | eventData.uintItems.setItem(1, "maxPrice", maxPrice);
385 | * | eventData.uintItems.setItem(2, "timestamp", timestamp);
386 | |
387 | * | eventEmitter.emitEventLog1(
388 | | "OraclePriceUpdate",
389 | * | Cast.toBytes32(token),
390 | * | eventData
391 | | );
392 | | }
393 | | }
394 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleModule.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./Oracle.sol";
6 | | import "../event/EventEmitter.sol";
7 | |
8 | | // @title OracleModule
9 | | // @dev Provides convenience functions for interacting with the Oracle
10 | | contract OracleModule {
11 | * | Oracle public immutable oracle;
12 | |
13 | | constructor(Oracle _oracle) {
14 | | oracle = _oracle;
15 | | }
16 | |
17 | | // @dev sets oracle prices, perform any additional tasks required,
18 | | // and clear the oracle prices after
19 | | //
20 | | // care should be taken to avoid re-entrancy while using this call
21 | | // since re-entrancy could allow functions to be called with prices
22 | | // meant for a different type of transaction
23 | | // the tokensWithPrices.length check in oracle.setPrices should help
24 | | // mitigate this
25 | | //
26 | | // @param params OracleUtils.SetPricesParams
27 | * | modifier withOraclePrices(
28 | | OracleUtils.SetPricesParams memory params
29 | | ) {
30 | * | oracle.setPrices(params);
31 | | _;
32 | * | oracle.clearAllPrices();
33 | | }
34 | |
35 | * | modifier withOraclePricesForAtomicAction(
36 | | OracleUtils.SetPricesParams memory params
37 | | ) {
38 | * | oracle.setPricesForAtomicAction(params);
39 | | _;
40 | | oracle.clearAllPrices();
41 | | }
42 | |
43 | | // @dev set oracle prices for a simulation
44 | | // tokensWithPrices is not set in this function
45 | | // it is possible for withSimulatedOraclePrices to be called and a function
46 | | // using withOraclePrices to be called after
47 | | // or for a function using withOraclePrices to be called and withSimulatedOraclePrices
48 | | // called after
49 | | // this should not cause an issue because this transaction should always revert
50 | | // and any state changes based on simulated prices as well as the setting of simulated
51 | | // prices should not be persisted
52 | | // @param params OracleUtils.SimulatePricesParams
53 | | modifier withSimulatedOraclePrices(
54 | | OracleUtils.SimulatePricesParams memory params
55 | | ) {
56 | | if (params.primaryTokens.length != params.primaryPrices.length) {
57 | | revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);
58 | | }
59 | |
60 | | for (uint256 i; i < params.primaryTokens.length; i++) {
61 | | address token = params.primaryTokens[i];
62 | | Price.Props memory price = params.primaryPrices[i];
63 | | oracle.setPrimaryPrice(token, price);
64 | | }
65 | |
66 | | oracle.setTimestamps(params.minTimestamp, params.maxTimestamp);
67 | |
68 | | _;
69 | |
70 | | revert Errors.EndOfOracleSimulation();
71 | | }
72 | | }
73 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleStore.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../role/RoleModule.sol";
6 | | import "../event/EventEmitter.sol";
7 | | import "../event/EventUtils.sol";
8 | | import "../utils/Cast.sol";
9 | |
10 | | // @title OracleStore
11 | | // @dev Stores the list of oracle signers
12 | * | contract OracleStore is RoleModule {
13 | | using EnumerableSet for EnumerableSet.AddressSet;
14 | | using EnumerableValues for EnumerableSet.AddressSet;
15 | |
16 | | using EventUtils for EventUtils.AddressItems;
17 | | using EventUtils for EventUtils.UintItems;
18 | | using EventUtils for EventUtils.IntItems;
19 | | using EventUtils for EventUtils.BoolItems;
20 | | using EventUtils for EventUtils.Bytes32Items;
21 | | using EventUtils for EventUtils.BytesItems;
22 | | using EventUtils for EventUtils.StringItems;
23 | |
24 | | EventEmitter public immutable eventEmitter;
25 | |
26 | | EnumerableSet.AddressSet internal signers;
27 | |
28 | | constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {
29 | | eventEmitter = _eventEmitter;
30 | | }
31 | |
32 | | // @dev adds a signer
33 | | // @param account address of the signer to add
34 | | function addSigner(address account) external onlyController {
35 | | signers.add(account);
36 | |
37 | | EventUtils.EventLogData memory eventData;
38 | | eventData.addressItems.initItems(1);
39 | | eventData.addressItems.setItem(0, "account", account);
40 | |
41 | | eventEmitter.emitEventLog1(
42 | | "SignerAdded",
43 | | Cast.toBytes32(account),
44 | | eventData
45 | | );
46 | | }
47 | |
48 | | // @dev removes a signer
49 | | // @param account address of the signer to remove
50 | | function removeSigner(address account) external onlyController {
51 | | signers.remove(account);
52 | |
53 | | EventUtils.EventLogData memory eventData;
54 | | eventData.addressItems.initItems(1);
55 | | eventData.addressItems.setItem(0, "account", account);
56 | |
57 | | eventEmitter.emitEventLog1(
58 | | "SignerRemoved",
59 | | Cast.toBytes32(account),
60 | | eventData
61 | | );
62 | | }
63 | |
64 | | // @dev get the total number of signers
65 | | // @return the total number of signers
66 | | function getSignerCount() external view returns (uint256) {
67 | | return signers.length();
68 | | }
69 | |
70 | | // @dev get the signer at the specified index
71 | | // @param index the index of the signer to get
72 | | // @return the signer at the specified index
73 | | function getSigner(uint256 index) external view returns (address) {
74 | | return signers.at(index);
75 | | }
76 | |
77 | | // @dev get the signers for the specified indexes
78 | | // @param start the start index, the value for this index will be included
79 | | // @param end the end index, the value for this index will not be included
80 | | // @return the signers for the specified indexes
81 | | function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {
82 | | return signers.valuesAt(start, end);
83 | | }
84 | | }
85 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/Array.sol";
6 | | import "../utils/Bits.sol";
7 | | import "../price/Price.sol";
8 | | import "../utils/Printer.sol";
9 | |
10 | | // @title OracleUtils
11 | | // @dev Library for oracle functions
12 | * | library OracleUtils {
13 | | using Array for uint256[];
14 | |
15 | | struct SetPricesParams {
16 | | address[] tokens;
17 | | address[] providers;
18 | | bytes[] data;
19 | | }
20 | |
21 | | struct ValidatedPrice {
22 | | address token;
23 | | uint256 min;
24 | | uint256 max;
25 | | uint256 timestamp;
26 | | address provider;
27 | | }
28 | |
29 | | struct SimulatePricesParams {
30 | | address[] primaryTokens;
31 | | Price.Props[] primaryPrices;
32 | | uint256 minTimestamp;
33 | | uint256 maxTimestamp;
34 | | }
35 | |
36 | * | function isOracleError(bytes4 errorSelector) internal pure returns (bool) {
37 | * | if (isOracleTimestampError(errorSelector)) {
38 | * | return true;
39 | | }
40 | |
41 | * | if (isEmptyPriceError(errorSelector)) {
42 | | return true;
43 | | }
44 | |
45 | * | return false;
46 | | }
47 | |
48 | * | function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {
49 | * | if (errorSelector == Errors.EmptyPrimaryPrice.selector) {
50 | | return true;
51 | | }
52 | |
53 | * | return false;
54 | | }
55 | |
56 | * | function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {
57 | * | if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {
58 | * | return true;
59 | | }
60 | |
61 | * | if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {
62 | * | return true;
63 | | }
64 | |
65 | * | return false;
66 | | }
67 | | }
68 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/AutoCancelUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../error/Errors.sol";
8 | |
9 | * | library AutoCancelUtils {
10 | * | function addAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal {
11 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);
12 | * | uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore);
13 | * | uint256 count = dataStore.getBytes32Count(listKey);
14 | * | if (count >= maxAutoCancelOrders) {
15 | | revert Errors.MaxAutoCancelOrdersExceeded(count, maxAutoCancelOrders);
16 | | }
17 | |
18 | * | dataStore.addBytes32(listKey, orderKey);
19 | | }
20 | |
21 | * | function removeAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal {
22 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);
23 | * | dataStore.removeBytes32(listKey, orderKey);
24 | | }
25 | |
26 | * | function getAutoCancelOrderKeys(DataStore dataStore, bytes32 positionKey) internal view returns (bytes32[] memory) {
27 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey);
28 | * | uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore);
29 | * | return dataStore.getBytes32ValuesAt(listKey, 0, maxAutoCancelOrders);
30 | | }
31 | |
32 | * | function getMaxAutoCancelOrders(DataStore dataStore) internal view returns (uint256) {
33 | * | return dataStore.getUint(Keys.MAX_AUTO_CANCEL_ORDERS);
34 | | }
35 | | }
36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/BaseOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./Order.sol";
6 | | import "../market/Market.sol";
7 | |
8 | | import "../data/DataStore.sol";
9 | | import "../event/EventEmitter.sol";
10 | | import "../referral/IReferralStorage.sol";
11 | |
12 | | import "../order/OrderVault.sol";
13 | | import "../order/IBaseOrderUtils.sol";
14 | | import "../position/PositionUtils.sol";
15 | |
16 | | import "../oracle/Oracle.sol";
17 | | import "../swap/SwapHandler.sol";
18 | |
19 | | // @title Order
20 | | // @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils
21 | | // DecreaseOrderUtils, SwapOrderUtils
22 | * | library BaseOrderUtils {
23 | | using SafeCast for int256;
24 | | using SafeCast for uint256;
25 | |
26 | | using Order for Order.Props;
27 | | using Price for Price.Props;
28 | |
29 | | // @dev ExecuteOrderParams struct used in executeOrder to avoid stack
30 | | // too deep errors
31 | | //
32 | | // @param contracts ExecuteOrderParamsContracts
33 | | // @param key the key of the order to execute
34 | | // @param order the order to execute
35 | | // @param swapPathMarkets the market values of the markets in the swapPath
36 | | // @param minOracleTimestamp the min oracle timestamp
37 | | // @param maxOracleTimestamp the max oracle timestamp
38 | | // @param market market values of the trading market
39 | | // @param keeper the keeper sending the transaction
40 | | // @param startingGas the starting gas
41 | | // @param secondaryOrderType the secondary order type
42 | | struct ExecuteOrderParams {
43 | | ExecuteOrderParamsContracts contracts;
44 | | bytes32 key;
45 | | Order.Props order;
46 | | Market.Props[] swapPathMarkets;
47 | | uint256 minOracleTimestamp;
48 | | uint256 maxOracleTimestamp;
49 | | Market.Props market;
50 | | address keeper;
51 | | uint256 startingGas;
52 | | Order.SecondaryOrderType secondaryOrderType;
53 | | }
54 | |
55 | | // @param dataStore DataStore
56 | | // @param eventEmitter EventEmitter
57 | | // @param orderVault OrderVault
58 | | // @param oracle Oracle
59 | | // @param swapHandler SwapHandler
60 | | // @param referralStorage IReferralStorage
61 | | struct ExecuteOrderParamsContracts {
62 | | DataStore dataStore;
63 | | EventEmitter eventEmitter;
64 | | OrderVault orderVault;
65 | | Oracle oracle;
66 | | SwapHandler swapHandler;
67 | | IReferralStorage referralStorage;
68 | | }
69 | |
70 | | struct GetExecutionPriceCache {
71 | | uint256 price;
72 | | uint256 executionPrice;
73 | | int256 adjustedPriceImpactUsd;
74 | | }
75 | |
76 | | // @dev check if an orderType is a market order
77 | | // @param orderType the order type
78 | | // @return whether an orderType is a market order
79 | * | function isMarketOrder(Order.OrderType orderType) internal pure returns (bool) {
80 | | // a liquidation order is not considered as a market order
81 | * | return orderType == Order.OrderType.MarketSwap ||
82 | * | orderType == Order.OrderType.MarketIncrease ||
83 | * | orderType == Order.OrderType.MarketDecrease;
84 | | }
85 | |
86 | | // @dev check if an orderType is a limit order
87 | | // @param orderType the order type
88 | | // @return whether an orderType is a limit order
89 | | function isLimitOrder(Order.OrderType orderType) internal pure returns (bool) {
90 | | return orderType == Order.OrderType.LimitSwap ||
91 | | orderType == Order.OrderType.LimitIncrease ||
92 | | orderType == Order.OrderType.LimitDecrease;
93 | | }
94 | |
95 | | // @dev check if an orderType is a swap order
96 | | // @param orderType the order type
97 | | // @return whether an orderType is a swap order
98 | * | function isSwapOrder(Order.OrderType orderType) internal pure returns (bool) {
99 | * | return orderType == Order.OrderType.MarketSwap ||
100 | * | orderType == Order.OrderType.LimitSwap;
101 | | }
102 | |
103 | | // @dev check if an orderType is a position order
104 | | // @param orderType the order type
105 | | // @return whether an orderType is a position order
106 | * | function isPositionOrder(Order.OrderType orderType) internal pure returns (bool) {
107 | * | return isIncreaseOrder(orderType) || isDecreaseOrder(orderType);
108 | | }
109 | |
110 | | // @dev check if an orderType is an increase order
111 | | // @param orderType the order type
112 | | // @return whether an orderType is an increase order
113 | * | function isIncreaseOrder(Order.OrderType orderType) internal pure returns (bool) {
114 | * | return orderType == Order.OrderType.MarketIncrease ||
115 | * | orderType == Order.OrderType.LimitIncrease;
116 | | }
117 | |
118 | | // @dev check if an orderType is a decrease order
119 | | // @param orderType the order type
120 | | // @return whether an orderType is a decrease order
121 | * | function isDecreaseOrder(Order.OrderType orderType) internal pure returns (bool) {
122 | * | return orderType == Order.OrderType.MarketDecrease ||
123 | * | orderType == Order.OrderType.LimitDecrease ||
124 | * | orderType == Order.OrderType.StopLossDecrease ||
125 | * | orderType == Order.OrderType.Liquidation;
126 | | }
127 | |
128 | | // @dev check if an orderType is a liquidation order
129 | | // @param orderType the order type
130 | | // @return whether an orderType is a liquidation order
131 | * | function isLiquidationOrder(Order.OrderType orderType) internal pure returns (bool) {
132 | * | return orderType == Order.OrderType.Liquidation;
133 | | }
134 | |
135 | | // @dev validate the price for increase / decrease orders based on the triggerPrice
136 | | // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice
137 | | //
138 | | // it is possible to update the oracle to support a primaryPrice and a secondaryPrice
139 | | // which would allow for stop-loss orders to be executed at exactly the triggerPrice
140 | | //
141 | | // however, this may lead to gaming issues, an example:
142 | | // - the current price is $2020
143 | | // - a user has a long position and creates a stop-loss decrease order for < $2010
144 | | // - if the order has a swap from ETH to USDC and the user is able to cause the order
145 | | // to be frozen / unexecutable by manipulating state or otherwise
146 | | // - then if price decreases to $2000, and the user is able to manipulate state such that
147 | | // the order becomes executable with $2010 being used as the price instead
148 | | // - then the user would be able to perform the swap at a higher price than should possible
149 | | //
150 | | // additionally, using the exact order's triggerPrice could lead to gaming issues during times
151 | | // of volatility due to users setting tight stop-losses to minimize loss while betting on a
152 | | // directional price movement, fees and price impact should help a bit with this, but there
153 | | // still may be some probability of success
154 | | //
155 | | // the order keepers can use the closest oracle price to the triggerPrice for execution, which
156 | | // should lead to similar order execution prices with reduced gaming risks
157 | | //
158 | | // if an order is frozen, the frozen order keepers should use the most recent price for order
159 | | // execution instead
160 | | //
161 | | // @param oracle Oracle
162 | | // @param indexToken the index token
163 | | // @param orderType the order type
164 | | // @param triggerPrice the order's triggerPrice
165 | | // @param isLong whether the order is for a long or short
166 | * | function validateOrderTriggerPrice(
167 | | Oracle oracle,
168 | | address indexToken,
169 | | Order.OrderType orderType,
170 | | uint256 triggerPrice,
171 | | bool isLong
172 | | ) internal view {
173 | * | if (
174 | * | isSwapOrder(orderType) ||
175 | * | isMarketOrder(orderType) ||
176 | * | isLiquidationOrder(orderType)
177 | | ) {
178 | * | return;
179 | | }
180 | |
181 | * | Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);
182 | |
183 | | // for limit increase long positions:
184 | | // - the order should be executed when the oracle price is <= triggerPrice
185 | | // - primaryPrice.max should be used for the oracle price
186 | | // for limit increase short positions:
187 | | // - the order should be executed when the oracle price is >= triggerPrice
188 | | // - primaryPrice.min should be used for the oracle price
189 | * | if (orderType == Order.OrderType.LimitIncrease) {
190 | * | bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;
191 | |
192 | * | if (!ok) {
193 | * | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
194 | | }
195 | |
196 | * | return;
197 | | }
198 | |
199 | | // for limit decrease long positions:
200 | | // - the order should be executed when the oracle price is >= triggerPrice
201 | | // - primaryPrice.min should be used for the oracle price
202 | | // for limit decrease short positions:
203 | | // - the order should be executed when the oracle price is <= triggerPrice
204 | | // - primaryPrice.max should be used for the oracle price
205 | * | if (orderType == Order.OrderType.LimitDecrease) {
206 | | bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;
207 | |
208 | | if (!ok) {
209 | | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
210 | | }
211 | |
212 | | return;
213 | | }
214 | |
215 | | // for stop-loss decrease long positions:
216 | | // - the order should be executed when the oracle price is <= triggerPrice
217 | | // - primaryPrice.min should be used for the oracle price
218 | | // for stop-loss decrease short positions:
219 | | // - the order should be executed when the oracle price is >= triggerPrice
220 | | // - primaryPrice.max should be used for the oracle price
221 | * | if (orderType == Order.OrderType.StopLossDecrease) {
222 | * | bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;
223 | |
224 | * | if (!ok) {
225 | | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
226 | | }
227 | |
228 | * | return;
229 | | }
230 | |
231 | | revert Errors.UnsupportedOrderType(uint256(orderType));
232 | | }
233 | |
234 | * | function getExecutionPriceForIncrease(
235 | | uint256 sizeDeltaUsd,
236 | | uint256 sizeDeltaInTokens,
237 | | uint256 acceptablePrice,
238 | | bool isLong
239 | * | ) internal pure returns (uint256) {
240 | * | if (sizeDeltaInTokens == 0) {
241 | * | revert Errors.EmptySizeDeltaInTokens();
242 | | }
243 | |
244 | * | uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;
245 | |
246 | | // increase order:
247 | | // - long: executionPrice should be smaller than acceptablePrice
248 | | // - short: executionPrice should be larger than acceptablePrice
249 | * | if (
250 | * | (isLong && executionPrice <= acceptablePrice) ||
251 | * | (!isLong && executionPrice >= acceptablePrice)
252 | | ) {
253 | * | return executionPrice;
254 | | }
255 | |
256 | | // the validateOrderTriggerPrice function should have validated if the price fulfills
257 | | // the order's trigger price
258 | | //
259 | | // for increase orders, the negative price impact is not capped
260 | | //
261 | | // for both increase and decrease orders, if it is due to price impact that the
262 | | // order cannot be fulfilled then the order should be frozen
263 | | //
264 | | // this is to prevent gaming by manipulation of the price impact value
265 | | //
266 | | // usually it should be costly to game the price impact value
267 | | // however, for certain cases, e.g. a user already has a large position opened
268 | | // the user may create limit orders that would only trigger after they close
269 | | // their position, this gives the user the option to cancel the pending order if
270 | | // prices do not move in their favour or to close their position and let the order
271 | | // execute if prices move in their favour
272 | | //
273 | | // it may also be possible for users to prevent the execution of orders from other users
274 | | // by manipulating the price impact, though this should be costly
275 | * | revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);
276 | | }
277 | |
278 | * | function getExecutionPriceForDecrease(
279 | | Price.Props memory indexTokenPrice,
280 | | uint256 positionSizeInUsd,
281 | | uint256 positionSizeInTokens,
282 | | uint256 sizeDeltaUsd,
283 | | int256 priceImpactUsd,
284 | | uint256 acceptablePrice,
285 | | bool isLong
286 | * | ) internal pure returns (uint256) {
287 | * | GetExecutionPriceCache memory cache;
288 | |
289 | | // decrease order:
290 | | // - long: use the smaller price
291 | | // - short: use the larger price
292 | * | cache.price = indexTokenPrice.pickPrice(!isLong);
293 | * | cache.executionPrice = cache.price;
294 | |
295 | | // using closing of long positions as an example
296 | | // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens
297 | | // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd
298 | | // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd
299 | | // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens
300 | | // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)
301 | | // priceImpactUsd should adjust the execution price such that:
302 | | // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] -
303 | | // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd
304 | | //
305 | | // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd)
306 | | // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd)
307 | | // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd
308 | | //
309 | | // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd
310 | | // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd
311 | | // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)
312 | | // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens)
313 | | // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens)
314 | | // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd
315 | | //
316 | | // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5
317 | | // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600
318 | | // realizedPnl based on price, without price impact: 0
319 | | // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000
320 | |
321 | | // a positive adjustedPriceImpactUsd would decrease the executionPrice
322 | | // a negative adjustedPriceImpactUsd would increase the executionPrice
323 | |
324 | | // for increase orders, the adjustedPriceImpactUsd is added to the divisor
325 | | // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice
326 | | // increase long order:
327 | | // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice
328 | | // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice
329 | | // increase short order:
330 | | // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice
331 | | // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice
332 | |
333 | | // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator
334 | | // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice
335 | | // decrease long order:
336 | | // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice
337 | | // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice
338 | | // decrease short order:
339 | | // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice
340 | | // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice
341 | | // adjust price by price impact
342 | * | if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {
343 | * | cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;
344 | |
345 | * | if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {
346 | | revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);
347 | | }
348 | |
349 | * | int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();
350 | * | int256 _executionPrice = cache.price.toInt256() + adjustment;
351 | |
352 | * | if (_executionPrice < 0) {
353 | | revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);
354 | | }
355 | |
356 | * | cache.executionPrice = _executionPrice.toUint256();
357 | | }
358 | |
359 | | // decrease order:
360 | | // - long: executionPrice should be larger than acceptablePrice
361 | | // - short: executionPrice should be smaller than acceptablePrice
362 | * | if (
363 | * | (isLong && cache.executionPrice >= acceptablePrice) ||
364 | * | (!isLong && cache.executionPrice <= acceptablePrice)
365 | | ) {
366 | * | return cache.executionPrice;
367 | | }
368 | |
369 | | // the validateOrderTriggerPrice function should have validated if the price fulfills
370 | | // the order's trigger price
371 | | //
372 | | // for decrease orders, the price impact should already be capped, so if the user
373 | | // had set an acceptable price within the range of the capped price impact, then
374 | | // the order should be fulfillable at the acceptable price
375 | | //
376 | | // for increase orders, the negative price impact is not capped
377 | | //
378 | | // for both increase and decrease orders, if it is due to price impact that the
379 | | // order cannot be fulfilled then the order should be frozen
380 | | //
381 | | // this is to prevent gaming by manipulation of the price impact value
382 | | //
383 | | // usually it should be costly to game the price impact value
384 | | // however, for certain cases, e.g. a user already has a large position opened
385 | | // the user may create limit orders that would only trigger after they close
386 | | // their position, this gives the user the option to cancel the pending order if
387 | | // prices do not move in their favour or to close their position and let the order
388 | | // execute if prices move in their favour
389 | | //
390 | | // it may also be possible for users to prevent the execution of orders from other users
391 | | // by manipulating the price impact, though this should be costly
392 | * | revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);
393 | | }
394 | |
395 | | // @dev validate that an order exists
396 | | // @param order the order to check
397 | * | function validateNonEmptyOrder(Order.Props memory order) internal pure {
398 | * | if (order.account() == address(0)) {
399 | | revert Errors.EmptyOrder();
400 | | }
401 | |
402 | * | if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {
403 | * | revert Errors.EmptyOrder();
404 | | }
405 | | }
406 | |
407 | * | function getPositionKey(Order.Props memory order) internal pure returns (bytes32) {
408 | * | if (isDecreaseOrder(order.orderType())) {
409 | * | return Position.getPositionKey(
410 | * | order.account(),
411 | * | order.market(),
412 | * | order.initialCollateralToken(),
413 | * | order.isLong()
414 | | );
415 | | }
416 | |
417 | | revert Errors.UnsupportedOrderType(uint256(order.orderType()));
418 | | }
419 | | }
420 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/DecreaseOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderUtils.sol";
6 | | import "../swap/SwapUtils.sol";
7 | | import "../position/DecreasePositionUtils.sol";
8 | | import "../order/OrderStoreUtils.sol";
9 | | import "../error/ErrorUtils.sol";
10 | |
11 | | // @title DecreaseOrderUtils
12 | | // @dev Library for functions to help with processing a decrease order
13 | | // note that any updates to the eventData
14 | * | library DecreaseOrderUtils {
15 | | using Position for Position.Props;
16 | | using Order for Order.Props;
17 | | using Array for uint256[];
18 | |
19 | | using EventUtils for EventUtils.AddressItems;
20 | | using EventUtils for EventUtils.UintItems;
21 | | using EventUtils for EventUtils.IntItems;
22 | | using EventUtils for EventUtils.BoolItems;
23 | | using EventUtils for EventUtils.Bytes32Items;
24 | | using EventUtils for EventUtils.BytesItems;
25 | | using EventUtils for EventUtils.StringItems;
26 | |
27 | | // @dev process a decrease order
28 | | // @param params BaseOrderUtils.ExecuteOrderParams
29 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {
30 | * | Order.Props memory order = params.order;
31 | * | MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market);
32 | |
33 | * | bytes32 positionKey = Position.getPositionKey(order.account(), order.market(), order.initialCollateralToken(), order.isLong());
34 | * | Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey);
35 | * | PositionUtils.validateNonEmptyPosition(position);
36 | |
37 | * | validateOracleTimestamp(
38 | * | params.contracts.dataStore,
39 | * | order.orderType(),
40 | * | order.updatedAtTime(),
41 | * | position.increasedAtTime(),
42 | * | position.decreasedAtTime(),
43 | * | params.minOracleTimestamp,
44 | * | params.maxOracleTimestamp
45 | | );
46 | |
47 | * | DecreasePositionUtils.DecreasePositionResult memory result = DecreasePositionUtils.decreasePosition(
48 | * | PositionUtils.UpdatePositionParams(
49 | * | params.contracts,
50 | * | params.market,
51 | * | order,
52 | * | params.key,
53 | * | position,
54 | * | positionKey,
55 | * | params.secondaryOrderType
56 | | )
57 | | );
58 | |
59 | | // if the pnlToken and the collateralToken are different
60 | | // and if a swap fails or no swap was requested
61 | | // then it is possible to receive two separate tokens from decreasing
62 | | // the position
63 | | // transfer the two tokens to the user in this case and skip processing
64 | | // the swapPath
65 | * | if (result.secondaryOutputAmount > 0) {
66 | * | _validateOutputAmount(
67 | * | params.contracts.oracle,
68 | * | result.outputToken,
69 | * | result.outputAmount,
70 | * | result.secondaryOutputToken,
71 | * | result.secondaryOutputAmount,
72 | * | order.minOutputAmount()
73 | | );
74 | |
75 | * | MarketToken(payable(order.market())).transferOut(
76 | * | result.outputToken,
77 | * | order.receiver(),
78 | * | result.outputAmount,
79 | * | order.shouldUnwrapNativeToken()
80 | | );
81 | |
82 | * | MarketToken(payable(order.market())).transferOut(
83 | * | result.secondaryOutputToken,
84 | * | order.receiver(),
85 | * | result.secondaryOutputAmount,
86 | * | order.shouldUnwrapNativeToken()
87 | | );
88 | |
89 | * | return getOutputEventData(
90 | * | result.outputToken,
91 | * | result.outputAmount,
92 | * | result.secondaryOutputToken,
93 | * | result.secondaryOutputAmount,
94 | * | result.orderSizeDeltaUsd,
95 | * | result.orderInitialCollateralDeltaAmount
96 | | );
97 | | }
98 | |
99 | * | try params.contracts.swapHandler.swap(
100 | * | SwapUtils.SwapParams(
101 | * | params.contracts.dataStore,
102 | * | params.contracts.eventEmitter,
103 | * | params.contracts.oracle,
104 | * | Bank(payable(order.market())),
105 | * | params.key,
106 | * | result.outputToken,
107 | * | result.outputAmount,
108 | * | params.swapPathMarkets,
109 | * | 0,
110 | * | order.receiver(),
111 | * | order.uiFeeReceiver(),
112 | * | order.shouldUnwrapNativeToken()
113 | | )
114 | | ) returns (address tokenOut, uint256 swapOutputAmount) {
115 | * | _validateOutputAmount(
116 | * | params.contracts.oracle,
117 | * | tokenOut,
118 | * | swapOutputAmount,
119 | * | order.minOutputAmount()
120 | | );
121 | |
122 | * | return getOutputEventData(
123 | * | tokenOut,
124 | * | swapOutputAmount,
125 | * | address(0),
126 | * | 0,
127 | * | result.orderSizeDeltaUsd,
128 | * | result.orderInitialCollateralDeltaAmount
129 | | );
130 | | } catch (bytes memory reasonBytes) {
131 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
132 | |
133 | | _handleSwapError(
134 | | params.contracts.oracle,
135 | | order,
136 | | result,
137 | | reason,
138 | | reasonBytes
139 | | );
140 | |
141 | | return getOutputEventData(
142 | | result.outputToken,
143 | | result.outputAmount,
144 | | address(0),
145 | | 0,
146 | | result.orderSizeDeltaUsd,
147 | | result.orderInitialCollateralDeltaAmount
148 | | );
149 | | }
150 | | }
151 | |
152 | * | function validateOracleTimestamp(
153 | | DataStore dataStore,
154 | | Order.OrderType orderType,
155 | | uint256 orderUpdatedAtTime,
156 | | uint256 positionIncreasedAtTime,
157 | | uint256 positionDecreasedAtTime,
158 | | uint256 minOracleTimestamp,
159 | | uint256 maxOracleTimestamp
160 | | ) internal view {
161 | * | if (orderType == Order.OrderType.MarketDecrease) {
162 | * | if (minOracleTimestamp < orderUpdatedAtTime) {
163 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, orderUpdatedAtTime);
164 | | }
165 | |
166 | * | uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
167 | |
168 | * | if (maxOracleTimestamp > orderUpdatedAtTime + requestExpirationTime) {
169 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
170 | * | maxOracleTimestamp,
171 | * | orderUpdatedAtTime,
172 | * | requestExpirationTime
173 | | );
174 | | }
175 | * | return;
176 | | }
177 | |
178 | | // a user could attempt to frontrun prices by creating a limit decrease
179 | | // order without a position
180 | | // when price moves in the user's favour, the user would create a
181 | | // position then
182 | | // e.g. price is $5000, a user creates a stop-loss order to
183 | | // close a long position when price is below $5000
184 | | // if price decreases to $4995, the user opens a long position at
185 | | // price $4995
186 | | // since slightly older prices may be used to execute a position
187 | | // the user's stop-loss order could be executed at price $5000
188 | | // for this reason, both the orderUpdatedAtTime and the
189 | | // positionIncreasedAtTime need to be used as a reference
190 | | //
191 | | // if there are multiple decrease orders, an execution of one decrease
192 | | // order would update the position, so the reference check here is only
193 | | // with positionIncreasedAtTime instead of a positionUpdatedAtTime value
194 | * | if (
195 | * | orderType == Order.OrderType.LimitDecrease ||
196 | * | orderType == Order.OrderType.StopLossDecrease
197 | | ) {
198 | * | uint256 latestUpdatedAtTime = orderUpdatedAtTime > positionIncreasedAtTime ? orderUpdatedAtTime : positionIncreasedAtTime;
199 | * | if (minOracleTimestamp < latestUpdatedAtTime) {
200 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime);
201 | | }
202 | * | return;
203 | | }
204 | |
205 | * | if (orderType == Order.OrderType.Liquidation) {
206 | * | uint256 latestUpdatedAtTime = positionIncreasedAtTime > positionDecreasedAtTime ? positionIncreasedAtTime : positionDecreasedAtTime;
207 | * | if (minOracleTimestamp < latestUpdatedAtTime) {
208 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime);
209 | | }
210 | * | return;
211 | | }
212 | |
213 | | revert Errors.UnsupportedOrderType(uint256(orderType));
214 | | }
215 | |
216 | | // note that minOutputAmount is treated as a USD value for this validation
217 | * | function _validateOutputAmount(
218 | | Oracle oracle,
219 | | address outputToken,
220 | | uint256 outputAmount,
221 | | uint256 minOutputAmount
222 | * | ) internal view {
223 | * | uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min;
224 | * | uint256 outputUsd = outputAmount * outputTokenPrice;
225 | |
226 | * | if (outputUsd < minOutputAmount) {
227 | | revert Errors.InsufficientOutputAmount(outputUsd, minOutputAmount);
228 | | }
229 | | }
230 | |
231 | | // note that minOutputAmount is treated as a USD value for this validation
232 | * | function _validateOutputAmount(
233 | | Oracle oracle,
234 | | address outputToken,
235 | | uint256 outputAmount,
236 | | address secondaryOutputToken,
237 | | uint256 secondaryOutputAmount,
238 | | uint256 minOutputAmount
239 | * | ) internal view {
240 | * | uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min;
241 | * | uint256 outputUsd = outputAmount * outputTokenPrice;
242 | |
243 | * | uint256 secondaryOutputTokenPrice = oracle.getPrimaryPrice(secondaryOutputToken).min;
244 | * | uint256 secondaryOutputUsd = secondaryOutputAmount * secondaryOutputTokenPrice;
245 | |
246 | * | uint256 totalOutputUsd = outputUsd + secondaryOutputUsd;
247 | |
248 | * | if (totalOutputUsd < minOutputAmount) {
249 | | revert Errors.InsufficientOutputAmount(totalOutputUsd, minOutputAmount);
250 | | }
251 | | }
252 | |
253 | | function _handleSwapError(
254 | | Oracle oracle,
255 | | Order.Props memory order,
256 | | DecreasePositionUtils.DecreasePositionResult memory result,
257 | | string memory reason,
258 | | bytes memory reasonBytes
259 | | ) internal {
260 | | emit SwapUtils.SwapReverted(reason, reasonBytes);
261 | |
262 | | _validateOutputAmount(
263 | | oracle,
264 | | result.outputToken,
265 | | result.outputAmount,
266 | | order.minOutputAmount()
267 | | );
268 | |
269 | | MarketToken(payable(order.market())).transferOut(
270 | | result.outputToken,
271 | | order.receiver(),
272 | | result.outputAmount,
273 | | order.shouldUnwrapNativeToken()
274 | | );
275 | | }
276 | |
277 | * | function getOutputEventData(
278 | | address outputToken,
279 | | uint256 outputAmount,
280 | | address secondaryOutputToken,
281 | | uint256 secondaryOutputAmount,
282 | | uint256 orderSizeDeltaUsd,
283 | | uint256 orderInitialCollateralDeltaAmount
284 | * | ) internal pure returns (EventUtils.EventLogData memory) {
285 | * | EventUtils.EventLogData memory eventData;
286 | * | eventData.addressItems.initItems(2);
287 | * | eventData.addressItems.setItem(0, "outputToken", outputToken);
288 | * | eventData.addressItems.setItem(1, "secondaryOutputToken", secondaryOutputToken);
289 | |
290 | * | eventData.uintItems.initItems(4);
291 | * | eventData.uintItems.setItem(0, "outputAmount", outputAmount);
292 | * | eventData.uintItems.setItem(1, "secondaryOutputAmount", secondaryOutputAmount);
293 | * | eventData.uintItems.setItem(2, "orderSizeDeltaUsd", orderSizeDeltaUsd);
294 | * | eventData.uintItems.setItem(3, "orderInitialCollateralDeltaAmount", orderInitialCollateralDeltaAmount);
295 | |
296 | * | return eventData;
297 | | }
298 | | }
299 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/ExecuteOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./AutoCancelUtils.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../data/Keys.sol";
8 | |
9 | | import "./Order.sol";
10 | | import "./OrderVault.sol";
11 | | import "./OrderStoreUtils.sol";
12 | | import "./OrderEventUtils.sol";
13 | | import "./OrderUtils.sol";
14 | |
15 | | import "../nonce/NonceUtils.sol";
16 | | import "../oracle/Oracle.sol";
17 | | import "../oracle/OracleUtils.sol";
18 | | import "../event/EventEmitter.sol";
19 | |
20 | | import "./IncreaseOrderUtils.sol";
21 | | import "./DecreaseOrderUtils.sol";
22 | | import "./SwapOrderUtils.sol";
23 | | import "./BaseOrderUtils.sol";
24 | |
25 | | import "../swap/SwapUtils.sol";
26 | |
27 | | import "../gas/GasUtils.sol";
28 | | import "../callback/CallbackUtils.sol";
29 | |
30 | | import "../utils/Array.sol";
31 | | import "../utils/AccountUtils.sol";
32 | | import "../referral/ReferralUtils.sol";
33 | |
34 | * | library ExecuteOrderUtils {
35 | | using Order for Order.Props;
36 | | using Position for Position.Props;
37 | | using Price for Price.Props;
38 | | using Array for uint256[];
39 | |
40 | | // @dev executes an order
41 | | // @param params BaseOrderUtils.ExecuteOrderParams
42 | * | function executeOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal {
43 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
44 | * | params.startingGas -= gasleft() / 63;
45 | |
46 | * | OrderStoreUtils.remove(params.contracts.dataStore, params.key, params.order.account());
47 | |
48 | * | BaseOrderUtils.validateNonEmptyOrder(params.order);
49 | |
50 | * | BaseOrderUtils.validateOrderTriggerPrice(
51 | * | params.contracts.oracle,
52 | * | params.market.indexToken,
53 | * | params.order.orderType(),
54 | * | params.order.triggerPrice(),
55 | * | params.order.isLong()
56 | | );
57 | |
58 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(
59 | * | params.contracts.oracle,
60 | * | params.market
61 | | );
62 | |
63 | * | MarketUtils.distributePositionImpactPool(
64 | * | params.contracts.dataStore,
65 | * | params.contracts.eventEmitter,
66 | * | params.market.marketToken
67 | | );
68 | |
69 | * | PositionUtils.updateFundingAndBorrowingState(
70 | * | params.contracts.dataStore,
71 | * | params.contracts.eventEmitter,
72 | * | params.market,
73 | * | prices
74 | | );
75 | |
76 | * | EventUtils.EventLogData memory eventData = processOrder(params);
77 | |
78 | | // validate that internal state changes are correct before calling
79 | | // internal callbacks
80 | | // if the native token was transferred to the receiver in a swap
81 | | // it may be possible to invoke internal contracts before the validations
82 | | // are called
83 | * | if (params.market.marketToken != address(0)) {
84 | * | MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.market);
85 | | }
86 | * | MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.swapPathMarkets);
87 | |
88 | * | OrderUtils.updateAutoCancelList(params.contracts.dataStore, params.key, params.order, false);
89 | |
90 | * | OrderEventUtils.emitOrderExecuted(
91 | * | params.contracts.eventEmitter,
92 | * | params.key,
93 | * | params.order.account(),
94 | * | params.secondaryOrderType
95 | | );
96 | |
97 | * | CallbackUtils.afterOrderExecution(params.key, params.order, eventData);
98 | |
99 | | // the order.executionFee for liquidation / adl orders is zero
100 | | // gas costs for liquidations / adl is subsidised by the treasury
101 | * | GasUtils.payExecutionFee(
102 | * | params.contracts.dataStore,
103 | * | params.contracts.eventEmitter,
104 | * | params.contracts.orderVault,
105 | * | params.key,
106 | * | params.order.callbackContract(),
107 | * | params.order.executionFee(),
108 | * | params.startingGas,
109 | * | GasUtils.estimateOrderOraclePriceCount(params.order.swapPath().length),
110 | * | params.keeper,
111 | * | params.order.receiver()
112 | | );
113 | |
114 | | // clearAutoCancelOrders should be called after the main execution fee
115 | | // is called
116 | | // this is because clearAutoCancelOrders loops through each order for
117 | | // the associated position and calls cancelOrder, which pays the keeper
118 | | // based on the gas usage for each cancel order
119 | * | if (BaseOrderUtils.isDecreaseOrder(params.order.orderType())) {
120 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(params.order);
121 | * | uint256 sizeInUsd = params.contracts.dataStore.getUint(
122 | * | keccak256(abi.encode(positionKey, PositionStoreUtils.SIZE_IN_USD))
123 | | );
124 | * | if (sizeInUsd == 0) {
125 | * | OrderUtils.clearAutoCancelOrders(
126 | * | params.contracts.dataStore,
127 | * | params.contracts.eventEmitter,
128 | * | params.contracts.orderVault,
129 | * | positionKey,
130 | * | params.keeper
131 | | );
132 | | }
133 | | }
134 | | }
135 | |
136 | | // @dev process an order execution
137 | | // @param params BaseOrderUtils.ExecuteOrderParams
138 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {
139 | * | if (BaseOrderUtils.isIncreaseOrder(params.order.orderType())) {
140 | * | return IncreaseOrderUtils.processOrder(params);
141 | | }
142 | |
143 | * | if (BaseOrderUtils.isDecreaseOrder(params.order.orderType())) {
144 | * | return DecreaseOrderUtils.processOrder(params);
145 | | }
146 | |
147 | * | if (BaseOrderUtils.isSwapOrder(params.order.orderType())) {
148 | * | return SwapOrderUtils.processOrder(params);
149 | | }
150 | |
151 | | revert Errors.UnsupportedOrderType(uint256(params.order.orderType()));
152 | | }
153 | | }
154 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/IBaseOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./Order.sol";
6 | |
7 | | interface IBaseOrderUtils {
8 | | // @dev CreateOrderParams struct used in createOrder to avoid stack
9 | | // too deep errors
10 | | //
11 | | // @param addresses address values
12 | | // @param numbers number values
13 | | // @param orderType for order.orderType
14 | | // @param decreasePositionSwapType for order.decreasePositionSwapType
15 | | // @param isLong for order.isLong
16 | | // @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken
17 | | struct CreateOrderParams {
18 | | CreateOrderParamsAddresses addresses;
19 | | CreateOrderParamsNumbers numbers;
20 | | Order.OrderType orderType;
21 | | Order.DecreasePositionSwapType decreasePositionSwapType;
22 | | bool isLong;
23 | | bool shouldUnwrapNativeToken;
24 | | bool autoCancel;
25 | | bytes32 referralCode;
26 | | }
27 | |
28 | | struct CreateOrderParamsAddresses {
29 | | address receiver;
30 | | address cancellationReceiver;
31 | | address callbackContract;
32 | | address uiFeeReceiver;
33 | | address market;
34 | | address initialCollateralToken;
35 | | address[] swapPath;
36 | | }
37 | |
38 | | // @param sizeDeltaUsd for order.sizeDeltaUsd
39 | | // @param triggerPrice for order.triggerPrice
40 | | // @param acceptablePrice for order.acceptablePrice
41 | | // @param executionFee for order.executionFee
42 | | // @param callbackGasLimit for order.callbackGasLimit
43 | | // @param minOutputAmount for order.minOutputAmount
44 | | struct CreateOrderParamsNumbers {
45 | | uint256 sizeDeltaUsd;
46 | | uint256 initialCollateralDeltaAmount;
47 | | uint256 triggerPrice;
48 | | uint256 acceptablePrice;
49 | | uint256 executionFee;
50 | | uint256 callbackGasLimit;
51 | | uint256 minOutputAmount;
52 | | }
53 | | }
54 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/IncreaseOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderUtils.sol";
6 | | import "../swap/SwapUtils.sol";
7 | | import "../position/IncreasePositionUtils.sol";
8 | | import "../order/OrderStoreUtils.sol";
9 | | import "../callback/CallbackUtils.sol";
10 | |
11 | | // @title IncreaseOrderUtils
12 | | // @dev Library for functions to help with processing an increase order
13 | * | library IncreaseOrderUtils {
14 | | using Position for Position.Props;
15 | | using Order for Order.Props;
16 | | using Array for uint256[];
17 | |
18 | | // @dev process an increase order
19 | | // @param params BaseOrderUtils.ExecuteOrderParams
20 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {
21 | * | MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market);
22 | |
23 | * | (address collateralToken, uint256 collateralIncrementAmount) = SwapUtils.swap(SwapUtils.SwapParams(
24 | * | params.contracts.dataStore,
25 | * | params.contracts.eventEmitter,
26 | * | params.contracts.oracle,
27 | * | params.contracts.orderVault,
28 | * | params.key,
29 | * | params.order.initialCollateralToken(),
30 | * | params.order.initialCollateralDeltaAmount(),
31 | * | params.swapPathMarkets,
32 | * | params.order.minOutputAmount(),
33 | * | params.order.market(),
34 | * | params.order.uiFeeReceiver(),
35 | * | false
36 | | ));
37 | |
38 | * | MarketUtils.validateMarketCollateralToken(params.market, collateralToken);
39 | |
40 | * | bytes32 positionKey = Position.getPositionKey(params.order.account(), params.order.market(), collateralToken, params.order.isLong());
41 | * | Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey);
42 | |
43 | | // initialize position
44 | * | if (position.account() == address(0)) {
45 | * | position.setAccount(params.order.account());
46 | * | if (position.market() != address(0) || position.collateralToken() != address(0)) {
47 | | revert Errors.UnexpectedPositionState();
48 | | }
49 | |
50 | * | position.setMarket(params.order.market());
51 | * | position.setCollateralToken(collateralToken);
52 | * | position.setIsLong(params.order.isLong());
53 | | }
54 | |
55 | * | uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
56 | |
57 | * | if (params.minOracleTimestamp < params.order.updatedAtTime()) {
58 | | revert Errors.OracleTimestampsAreSmallerThanRequired(
59 | | params.minOracleTimestamp,
60 | | params.order.updatedAtTime()
61 | | );
62 | | }
63 | |
64 | * | if (
65 | * | params.order.orderType() == Order.OrderType.MarketIncrease &&
66 | * | params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime
67 | | ) {
68 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
69 | * | params.maxOracleTimestamp,
70 | * | params.order.updatedAtTime(),
71 | * | requestExpirationTime
72 | | );
73 | | }
74 | |
75 | * | IncreasePositionUtils.increasePosition(
76 | * | PositionUtils.UpdatePositionParams(
77 | * | params.contracts,
78 | * | params.market,
79 | * | params.order,
80 | * | params.key,
81 | * | position,
82 | * | positionKey,
83 | * | params.secondaryOrderType
84 | | ),
85 | * | collateralIncrementAmount
86 | | );
87 | |
88 | * | EventUtils.EventLogData memory eventData;
89 | * | return eventData;
90 | | }
91 | | }
92 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/Order.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../chain/Chain.sol";
6 | |
7 | | // @title Order
8 | | // @dev Struct for orders
9 | * | library Order {
10 | | using Order for Props;
11 | |
12 | | enum OrderType {
13 | | // @dev MarketSwap: swap token A to token B at the current market price
14 | | // the order will be cancelled if the minOutputAmount cannot be fulfilled
15 | | MarketSwap,
16 | | // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled
17 | | LimitSwap,
18 | | // @dev MarketIncrease: increase position at the current market price
19 | | // the order will be cancelled if the position cannot be increased at the acceptablePrice
20 | | MarketIncrease,
21 | | // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled
22 | | LimitIncrease,
23 | | // @dev MarketDecrease: decrease position at the current market price
24 | | // the order will be cancelled if the position cannot be decreased at the acceptablePrice
25 | | MarketDecrease,
26 | | // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
27 | | LimitDecrease,
28 | | // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled
29 | | StopLossDecrease,
30 | | // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met
31 | | Liquidation
32 | | }
33 | |
34 | | // to help further differentiate orders
35 | | enum SecondaryOrderType {
36 | | None,
37 | | Adl
38 | | }
39 | |
40 | | enum DecreasePositionSwapType {
41 | | NoSwap,
42 | | SwapPnlTokenToCollateralToken,
43 | | SwapCollateralTokenToPnlToken
44 | | }
45 | |
46 | | // @dev there is a limit on the number of fields a struct can have when being passed
47 | | // or returned as a memory variable which can cause "Stack too deep" errors
48 | | // use sub-structs to avoid this issue
49 | | // @param addresses address values
50 | | // @param numbers number values
51 | | // @param flags boolean values
52 | | struct Props {
53 | | Addresses addresses;
54 | | Numbers numbers;
55 | | Flags flags;
56 | | }
57 | |
58 | | // @param account the account of the order
59 | | // @param receiver the receiver for any token transfers
60 | | // this field is meant to allow the output of an order to be
61 | | // received by an address that is different from the creator of the
62 | | // order whether this is for swaps or whether the account is the owner
63 | | // of a position
64 | | // for funding fees and claimable collateral, the funds are still
65 | | // credited to the owner of the position indicated by order.account
66 | | // @param callbackContract the contract to call for callbacks
67 | | // @param uiFeeReceiver the ui fee receiver
68 | | // @param market the trading market
69 | | // @param initialCollateralToken for increase orders, initialCollateralToken
70 | | // is the token sent in by the user, the token will be swapped through the
71 | | // specified swapPath, before being deposited into the position as collateral
72 | | // for decrease orders, initialCollateralToken is the collateral token of the position
73 | | // withdrawn collateral from the decrease of the position will be swapped
74 | | // through the specified swapPath
75 | | // for swaps, initialCollateralToken is the initial token sent for the swap
76 | | // @param swapPath an array of market addresses to swap through
77 | | struct Addresses {
78 | | address account;
79 | | address receiver;
80 | | address cancellationReceiver;
81 | | address callbackContract;
82 | | address uiFeeReceiver;
83 | | address market;
84 | | address initialCollateralToken;
85 | | address[] swapPath;
86 | | }
87 | |
88 | | // @param sizeDeltaUsd the requested change in position size
89 | | // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount
90 | | // is the amount of the initialCollateralToken sent in by the user
91 | | // for decrease orders, initialCollateralDeltaAmount is the amount of the position's
92 | | // collateralToken to withdraw
93 | | // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent
94 | | // in for the swap
95 | | // @param orderType the order type
96 | | // @param triggerPrice the trigger price for non-market orders
97 | | // @param acceptablePrice the acceptable execution price for increase / decrease orders
98 | | // @param executionFee the execution fee for keepers
99 | | // @param callbackGasLimit the gas limit for the callbackContract
100 | | // @param minOutputAmount the minimum output amount for decrease orders and swaps
101 | | // note that for decrease orders, multiple tokens could be received, for this reason, the
102 | | // minOutputAmount value is treated as a USD value for validation in decrease orders
103 | | // @param updatedAtBlock the block at which the order was last updated
104 | | struct Numbers {
105 | | OrderType orderType;
106 | | DecreasePositionSwapType decreasePositionSwapType;
107 | | uint256 sizeDeltaUsd;
108 | | uint256 initialCollateralDeltaAmount;
109 | | uint256 triggerPrice;
110 | | uint256 acceptablePrice;
111 | | uint256 executionFee;
112 | | uint256 callbackGasLimit;
113 | | uint256 minOutputAmount;
114 | | uint256 updatedAtBlock;
115 | | uint256 updatedAtTime;
116 | | }
117 | |
118 | | // @param isLong whether the order is for a long or short
119 | | // @param shouldUnwrapNativeToken whether to unwrap native tokens before
120 | | // transferring to the user
121 | | // @param isFrozen whether the order is frozen
122 | | struct Flags {
123 | | bool isLong;
124 | | bool shouldUnwrapNativeToken;
125 | | bool isFrozen;
126 | | bool autoCancel;
127 | | }
128 | |
129 | | // @dev the order account
130 | | // @param props Props
131 | | // @return the order account
132 | * | function account(Props memory props) internal pure returns (address) {
133 | * | return props.addresses.account;
134 | | }
135 | |
136 | | // @dev set the order account
137 | | // @param props Props
138 | | // @param value the value to set to
139 | * | function setAccount(Props memory props, address value) internal pure {
140 | * | props.addresses.account = value;
141 | | }
142 | |
143 | | // @dev the order receiver
144 | | // @param props Props
145 | | // @return the order receiver
146 | * | function receiver(Props memory props) internal pure returns (address) {
147 | * | return props.addresses.receiver;
148 | | }
149 | |
150 | | // @dev set the order receiver
151 | | // @param props Props
152 | | // @param value the value to set to
153 | * | function setReceiver(Props memory props, address value) internal pure {
154 | * | props.addresses.receiver = value;
155 | | }
156 | |
157 | * | function cancellationReceiver(Props memory props) internal pure returns (address) {
158 | * | return props.addresses.cancellationReceiver;
159 | | }
160 | |
161 | * | function setCancellationReceiver(Props memory props, address value) internal pure {
162 | * | props.addresses.cancellationReceiver = value;
163 | | }
164 | |
165 | | // @dev the order callbackContract
166 | | // @param props Props
167 | | // @return the order callbackContract
168 | * | function callbackContract(Props memory props) internal pure returns (address) {
169 | * | return props.addresses.callbackContract;
170 | | }
171 | |
172 | | // @dev set the order callbackContract
173 | | // @param props Props
174 | | // @param value the value to set to
175 | * | function setCallbackContract(Props memory props, address value) internal pure {
176 | * | props.addresses.callbackContract = value;
177 | | }
178 | |
179 | | // @dev the order market
180 | | // @param props Props
181 | | // @return the order market
182 | * | function market(Props memory props) internal pure returns (address) {
183 | * | return props.addresses.market;
184 | | }
185 | |
186 | | // @dev set the order market
187 | | // @param props Props
188 | | // @param value the value to set to
189 | * | function setMarket(Props memory props, address value) internal pure {
190 | * | props.addresses.market = value;
191 | | }
192 | |
193 | | // @dev the order initialCollateralToken
194 | | // @param props Props
195 | | // @return the order initialCollateralToken
196 | * | function initialCollateralToken(Props memory props) internal pure returns (address) {
197 | * | return props.addresses.initialCollateralToken;
198 | | }
199 | |
200 | | // @dev set the order initialCollateralToken
201 | | // @param props Props
202 | | // @param value the value to set to
203 | * | function setInitialCollateralToken(Props memory props, address value) internal pure {
204 | * | props.addresses.initialCollateralToken = value;
205 | | }
206 | |
207 | | // @dev the order uiFeeReceiver
208 | | // @param props Props
209 | | // @return the order uiFeeReceiver
210 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) {
211 | * | return props.addresses.uiFeeReceiver;
212 | | }
213 | |
214 | | // @dev set the order uiFeeReceiver
215 | | // @param props Props
216 | | // @param value the value to set to
217 | * | function setUiFeeReceiver(Props memory props, address value) internal pure {
218 | * | props.addresses.uiFeeReceiver = value;
219 | | }
220 | |
221 | | // @dev the order swapPath
222 | | // @param props Props
223 | | // @return the order swapPath
224 | * | function swapPath(Props memory props) internal pure returns (address[] memory) {
225 | * | return props.addresses.swapPath;
226 | | }
227 | |
228 | | // @dev set the order swapPath
229 | | // @param props Props
230 | | // @param value the value to set to
231 | * | function setSwapPath(Props memory props, address[] memory value) internal pure {
232 | * | props.addresses.swapPath = value;
233 | | }
234 | |
235 | | // @dev the order type
236 | | // @param props Props
237 | | // @return the order type
238 | * | function orderType(Props memory props) internal pure returns (OrderType) {
239 | * | return props.numbers.orderType;
240 | | }
241 | |
242 | | // @dev set the order type
243 | | // @param props Props
244 | | // @param value the value to set to
245 | * | function setOrderType(Props memory props, OrderType value) internal pure {
246 | * | props.numbers.orderType = value;
247 | | }
248 | |
249 | * | function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {
250 | * | return props.numbers.decreasePositionSwapType;
251 | | }
252 | |
253 | * | function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {
254 | * | props.numbers.decreasePositionSwapType = value;
255 | | }
256 | |
257 | | // @dev the order sizeDeltaUsd
258 | | // @param props Props
259 | | // @return the order sizeDeltaUsd
260 | * | function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {
261 | * | return props.numbers.sizeDeltaUsd;
262 | | }
263 | |
264 | | // @dev set the order sizeDeltaUsd
265 | | // @param props Props
266 | | // @param value the value to set to
267 | * | function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {
268 | * | props.numbers.sizeDeltaUsd = value;
269 | | }
270 | |
271 | | // @dev the order initialCollateralDeltaAmount
272 | | // @param props Props
273 | | // @return the order initialCollateralDeltaAmount
274 | * | function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {
275 | * | return props.numbers.initialCollateralDeltaAmount;
276 | | }
277 | |
278 | | // @dev set the order initialCollateralDeltaAmount
279 | | // @param props Props
280 | | // @param value the value to set to
281 | * | function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {
282 | * | props.numbers.initialCollateralDeltaAmount = value;
283 | | }
284 | |
285 | | // @dev the order triggerPrice
286 | | // @param props Props
287 | | // @return the order triggerPrice
288 | * | function triggerPrice(Props memory props) internal pure returns (uint256) {
289 | * | return props.numbers.triggerPrice;
290 | | }
291 | |
292 | | // @dev set the order triggerPrice
293 | | // @param props Props
294 | | // @param value the value to set to
295 | * | function setTriggerPrice(Props memory props, uint256 value) internal pure {
296 | * | props.numbers.triggerPrice = value;
297 | | }
298 | |
299 | | // @dev the order acceptablePrice
300 | | // @param props Props
301 | | // @return the order acceptablePrice
302 | * | function acceptablePrice(Props memory props) internal pure returns (uint256) {
303 | * | return props.numbers.acceptablePrice;
304 | | }
305 | |
306 | | // @dev set the order acceptablePrice
307 | | // @param props Props
308 | | // @param value the value to set to
309 | * | function setAcceptablePrice(Props memory props, uint256 value) internal pure {
310 | * | props.numbers.acceptablePrice = value;
311 | | }
312 | |
313 | | // @dev set the order executionFee
314 | | // @param props Props
315 | | // @param value the value to set to
316 | * | function setExecutionFee(Props memory props, uint256 value) internal pure {
317 | * | props.numbers.executionFee = value;
318 | | }
319 | |
320 | | // @dev the order executionFee
321 | | // @param props Props
322 | | // @return the order executionFee
323 | * | function executionFee(Props memory props) internal pure returns (uint256) {
324 | * | return props.numbers.executionFee;
325 | | }
326 | |
327 | | // @dev the order callbackGasLimit
328 | | // @param props Props
329 | | // @return the order callbackGasLimit
330 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) {
331 | * | return props.numbers.callbackGasLimit;
332 | | }
333 | |
334 | | // @dev set the order callbackGasLimit
335 | | // @param props Props
336 | | // @param value the value to set to
337 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
338 | * | props.numbers.callbackGasLimit = value;
339 | | }
340 | |
341 | | // @dev the order minOutputAmount
342 | | // @param props Props
343 | | // @return the order minOutputAmount
344 | * | function minOutputAmount(Props memory props) internal pure returns (uint256) {
345 | * | return props.numbers.minOutputAmount;
346 | | }
347 | |
348 | | // @dev set the order minOutputAmount
349 | | // @param props Props
350 | | // @param value the value to set to
351 | * | function setMinOutputAmount(Props memory props, uint256 value) internal pure {
352 | * | props.numbers.minOutputAmount = value;
353 | | }
354 | |
355 | | // @dev the order updatedAtBlock
356 | | // @param props Props
357 | | // @return the order updatedAtBlock
358 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) {
359 | * | return props.numbers.updatedAtBlock;
360 | | }
361 | |
362 | | // @dev set the order updatedAtBlock
363 | | // @param props Props
364 | | // @param value the value to set to
365 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
366 | * | props.numbers.updatedAtBlock = value;
367 | | }
368 | |
369 | | // @dev the order updatedAtTime
370 | | // @param props Props
371 | | // @return the order updatedAtTime
372 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) {
373 | * | return props.numbers.updatedAtTime;
374 | | }
375 | |
376 | | // @dev set the order updatedAtTime
377 | | // @param props Props
378 | | // @param value the value to set to
379 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
380 | * | props.numbers.updatedAtTime = value;
381 | | }
382 | |
383 | | // @dev whether the order is for a long or short
384 | | // @param props Props
385 | | // @return whether the order is for a long or short
386 | * | function isLong(Props memory props) internal pure returns (bool) {
387 | * | return props.flags.isLong;
388 | | }
389 | |
390 | | // @dev set whether the order is for a long or short
391 | | // @param props Props
392 | | // @param value the value to set to
393 | * | function setIsLong(Props memory props, bool value) internal pure {
394 | * | props.flags.isLong = value;
395 | | }
396 | |
397 | | // @dev whether to unwrap the native token before transfers to the user
398 | | // @param props Props
399 | | // @return whether to unwrap the native token before transfers to the user
400 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {
401 | * | return props.flags.shouldUnwrapNativeToken;
402 | | }
403 | |
404 | | // @dev set whether the native token should be unwrapped before being
405 | | // transferred to the receiver
406 | | // @param props Props
407 | | // @param value the value to set to
408 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {
409 | * | props.flags.shouldUnwrapNativeToken = value;
410 | | }
411 | |
412 | | // @dev whether the order is frozen
413 | | // @param props Props
414 | | // @return whether the order is frozen
415 | * | function isFrozen(Props memory props) internal pure returns (bool) {
416 | * | return props.flags.isFrozen;
417 | | }
418 | |
419 | | // @dev set whether the order is frozen
420 | | // transferred to the receiver
421 | | // @param props Props
422 | | // @param value the value to set to
423 | * | function setIsFrozen(Props memory props, bool value) internal pure {
424 | * | props.flags.isFrozen = value;
425 | | }
426 | |
427 | * | function autoCancel(Props memory props) internal pure returns (bool) {
428 | * | return props.flags.autoCancel;
429 | | }
430 | |
431 | * | function setAutoCancel(Props memory props, bool value) internal pure {
432 | * | props.flags.autoCancel = value;
433 | | }
434 | |
435 | | // @dev set the order.updatedAtBlock to the current block number
436 | | // @param props Props
437 | * | function touch(Props memory props) internal view {
438 | * | props.setUpdatedAtBlock(Chain.currentBlockNumber());
439 | * | props.setUpdatedAtTime(Chain.currentTimestamp());
440 | | }
441 | | }
442 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../utils/Cast.sol";
7 | |
8 | | import "./Order.sol";
9 | |
10 | * | library OrderEventUtils {
11 | | using Order for Order.Props;
12 | |
13 | | using EventUtils for EventUtils.AddressItems;
14 | | using EventUtils for EventUtils.UintItems;
15 | | using EventUtils for EventUtils.IntItems;
16 | | using EventUtils for EventUtils.BoolItems;
17 | | using EventUtils for EventUtils.Bytes32Items;
18 | | using EventUtils for EventUtils.BytesItems;
19 | | using EventUtils for EventUtils.StringItems;
20 | |
21 | * | function emitOrderCreated(
22 | | EventEmitter eventEmitter,
23 | | bytes32 key,
24 | | Order.Props memory order
25 | * | ) internal {
26 | * | EventUtils.EventLogData memory eventData;
27 | |
28 | * | eventData.addressItems.initItems(6);
29 | * | eventData.addressItems.setItem(0, "account", order.account());
30 | * | eventData.addressItems.setItem(1, "receiver", order.receiver());
31 | * | eventData.addressItems.setItem(2, "callbackContract", order.callbackContract());
32 | * | eventData.addressItems.setItem(3, "uiFeeReceiver", order.uiFeeReceiver());
33 | * | eventData.addressItems.setItem(4, "market", order.market());
34 | * | eventData.addressItems.setItem(5, "initialCollateralToken", order.initialCollateralToken());
35 | |
36 | * | eventData.addressItems.initArrayItems(1);
37 | * | eventData.addressItems.setItem(0, "swapPath", order.swapPath());
38 | |
39 | * | eventData.uintItems.initItems(11);
40 | * | eventData.uintItems.setItem(0, "orderType", uint256(order.orderType()));
41 | * | eventData.uintItems.setItem(1, "decreasePositionSwapType", uint256(order.decreasePositionSwapType()));
42 | * | eventData.uintItems.setItem(2, "sizeDeltaUsd", order.sizeDeltaUsd());
43 | * | eventData.uintItems.setItem(3, "initialCollateralDeltaAmount", order.initialCollateralDeltaAmount());
44 | * | eventData.uintItems.setItem(4, "triggerPrice", order.triggerPrice());
45 | * | eventData.uintItems.setItem(5, "acceptablePrice", order.acceptablePrice());
46 | * | eventData.uintItems.setItem(6, "executionFee", order.executionFee());
47 | * | eventData.uintItems.setItem(7, "callbackGasLimit", order.callbackGasLimit());
48 | * | eventData.uintItems.setItem(8, "minOutputAmount", order.minOutputAmount());
49 | * | eventData.uintItems.setItem(9, "updatedAtBlock", order.updatedAtBlock());
50 | * | eventData.uintItems.setItem(10, "updatedAtTime", order.updatedAtTime());
51 | |
52 | * | eventData.boolItems.initItems(3);
53 | * | eventData.boolItems.setItem(0, "isLong", order.isLong());
54 | * | eventData.boolItems.setItem(1, "shouldUnwrapNativeToken", order.shouldUnwrapNativeToken());
55 | * | eventData.boolItems.setItem(2, "isFrozen", order.isFrozen());
56 | |
57 | * | eventData.bytes32Items.initItems(1);
58 | * | eventData.bytes32Items.setItem(0, "key", key);
59 | |
60 | * | eventEmitter.emitEventLog2(
61 | | "OrderCreated",
62 | * | key,
63 | * | Cast.toBytes32(order.account()),
64 | * | eventData
65 | | );
66 | | }
67 | |
68 | * | function emitOrderExecuted(
69 | | EventEmitter eventEmitter,
70 | | bytes32 key,
71 | | address account,
72 | | Order.SecondaryOrderType secondaryOrderType
73 | * | ) internal {
74 | * | EventUtils.EventLogData memory eventData;
75 | |
76 | * | eventData.bytes32Items.initItems(1);
77 | * | eventData.bytes32Items.setItem(0, "key", key);
78 | |
79 | * | eventData.addressItems.initItems(1);
80 | * | eventData.addressItems.setItem(0, "account", account);
81 | |
82 | * | eventData.uintItems.initItems(1);
83 | * | eventData.uintItems.setItem(0, "secondaryOrderType", uint256(secondaryOrderType));
84 | |
85 | * | eventEmitter.emitEventLog2(
86 | | "OrderExecuted",
87 | * | key,
88 | * | Cast.toBytes32(account),
89 | * | eventData
90 | | );
91 | | }
92 | |
93 | | function emitOrderUpdated(
94 | | EventEmitter eventEmitter,
95 | | bytes32 key,
96 | | address account,
97 | | uint256 sizeDeltaUsd,
98 | | uint256 acceptablePrice,
99 | | uint256 triggerPrice,
100 | | uint256 minOutputAmount,
101 | | uint256 updatedAtTime
102 | | ) internal {
103 | | EventUtils.EventLogData memory eventData;
104 | |
105 | | eventData.bytes32Items.initItems(1);
106 | | eventData.bytes32Items.setItem(0, "key", key);
107 | |
108 | | eventData.addressItems.initItems(1);
109 | | eventData.addressItems.setItem(0, "account", account);
110 | |
111 | | eventData.uintItems.initItems(5);
112 | | eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd);
113 | | eventData.uintItems.setItem(1, "acceptablePrice", acceptablePrice);
114 | | eventData.uintItems.setItem(2, "triggerPrice", triggerPrice);
115 | | eventData.uintItems.setItem(3, "minOutputAmount", minOutputAmount);
116 | | eventData.uintItems.setItem(4, "updatedAtTime", updatedAtTime);
117 | |
118 | | eventEmitter.emitEventLog2(
119 | | "OrderUpdated",
120 | | key,
121 | | Cast.toBytes32(account),
122 | | eventData
123 | | );
124 | | }
125 | |
126 | * | function emitOrderSizeDeltaAutoUpdated(
127 | | EventEmitter eventEmitter,
128 | | bytes32 key,
129 | | uint256 sizeDeltaUsd,
130 | | uint256 nextSizeDeltaUsd
131 | * | ) internal {
132 | * | EventUtils.EventLogData memory eventData;
133 | |
134 | * | eventData.bytes32Items.initItems(1);
135 | * | eventData.bytes32Items.setItem(0, "key", key);
136 | |
137 | * | eventData.uintItems.initItems(2);
138 | * | eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd);
139 | * | eventData.uintItems.setItem(1, "nextSizeDeltaUsd", nextSizeDeltaUsd);
140 | |
141 | * | eventEmitter.emitEventLog1(
142 | | "OrderSizeDeltaAutoUpdated",
143 | * | key,
144 | * | eventData
145 | | );
146 | | }
147 | |
148 | * | function emitOrderCollateralDeltaAmountAutoUpdated(
149 | | EventEmitter eventEmitter,
150 | | bytes32 key,
151 | | uint256 collateralDeltaAmount,
152 | | uint256 nextCollateralDeltaAmount
153 | * | ) internal {
154 | * | EventUtils.EventLogData memory eventData;
155 | |
156 | * | eventData.bytes32Items.initItems(1);
157 | * | eventData.bytes32Items.setItem(0, "key", key);
158 | |
159 | * | eventData.uintItems.initItems(2);
160 | * | eventData.uintItems.setItem(0, "collateralDeltaAmount", collateralDeltaAmount);
161 | * | eventData.uintItems.setItem(1, "nextCollateralDeltaAmount", nextCollateralDeltaAmount);
162 | |
163 | * | eventEmitter.emitEventLog1(
164 | | "OrderCollateralDeltaAmountAutoUpdated",
165 | * | key,
166 | * | eventData
167 | | );
168 | | }
169 | |
170 | * | function emitOrderCancelled(
171 | | EventEmitter eventEmitter,
172 | | bytes32 key,
173 | | address account,
174 | | string memory reason,
175 | | bytes memory reasonBytes
176 | * | ) internal {
177 | * | EventUtils.EventLogData memory eventData;
178 | |
179 | * | eventData.bytes32Items.initItems(1);
180 | * | eventData.bytes32Items.setItem(0, "key", key);
181 | |
182 | * | eventData.addressItems.initItems(1);
183 | * | eventData.addressItems.setItem(0, "account", account);
184 | |
185 | * | eventData.stringItems.initItems(1);
186 | * | eventData.stringItems.setItem(0, "reason", reason);
187 | |
188 | * | eventData.bytesItems.initItems(1);
189 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
190 | |
191 | * | eventEmitter.emitEventLog2(
192 | | "OrderCancelled",
193 | * | key,
194 | * | Cast.toBytes32(account),
195 | * | eventData
196 | | );
197 | | }
198 | |
199 | * | function emitOrderFrozen(
200 | | EventEmitter eventEmitter,
201 | | bytes32 key,
202 | | address account,
203 | | string memory reason,
204 | | bytes memory reasonBytes
205 | * | ) internal {
206 | * | EventUtils.EventLogData memory eventData;
207 | |
208 | * | eventData.bytes32Items.initItems(1);
209 | * | eventData.bytes32Items.setItem(0, "key", key);
210 | |
211 | * | eventData.addressItems.initItems(1);
212 | * | eventData.addressItems.setItem(0, "account", account);
213 | |
214 | * | eventData.stringItems.initItems(1);
215 | * | eventData.stringItems.setItem(0, "reason", reason);
216 | |
217 | * | eventData.bytesItems.initItems(1);
218 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
219 | |
220 | * | eventEmitter.emitEventLog2(
221 | | "OrderFrozen",
222 | * | key,
223 | * | Cast.toBytes32(account),
224 | * | eventData
225 | | );
226 | | }
227 | | }
228 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Order.sol";
9 | |
10 | | /**
11 | | * @title OrderStoreUtils
12 | | * @dev Library for order storage functions
13 | | */
14 | * | library OrderStoreUtils {
15 | | using Order for Order.Props;
16 | |
17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER"));
19 | * | bytes32 internal constant CANCELLATION_RECEIVER = keccak256(abi.encode("CANCELLATION_RECEIVER"));
20 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
21 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
22 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET"));
23 | * | bytes32 internal constant INITIAL_COLLATERAL_TOKEN = keccak256(abi.encode("INITIAL_COLLATERAL_TOKEN"));
24 | * | bytes32 internal constant SWAP_PATH = keccak256(abi.encode("SWAP_PATH"));
25 | |
26 | * | bytes32 internal constant ORDER_TYPE = keccak256(abi.encode("ORDER_TYPE"));
27 | * | bytes32 internal constant DECREASE_POSITION_SWAP_TYPE = keccak256(abi.encode("DECREASE_POSITION_SWAP_TYPE"));
28 | * | bytes32 internal constant SIZE_DELTA_USD = keccak256(abi.encode("SIZE_DELTA_USD"));
29 | * | bytes32 internal constant INITIAL_COLLATERAL_DELTA_AMOUNT = keccak256(abi.encode("INITIAL_COLLATERAL_DELTA_AMOUNT"));
30 | * | bytes32 internal constant TRIGGER_PRICE = keccak256(abi.encode("TRIGGER_PRICE"));
31 | * | bytes32 internal constant ACCEPTABLE_PRICE = keccak256(abi.encode("ACCEPTABLE_PRICE"));
32 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
33 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
34 | * | bytes32 internal constant MIN_OUTPUT_AMOUNT = keccak256(abi.encode("MIN_OUTPUT_AMOUNT"));
35 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
36 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME"));
37 | |
38 | * | bytes32 internal constant IS_LONG = keccak256(abi.encode("IS_LONG"));
39 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
40 | * | bytes32 internal constant IS_FROZEN = keccak256(abi.encode("IS_FROZEN"));
41 | * | bytes32 internal constant AUTO_CANCEL = keccak256(abi.encode("AUTO_CANCEL"));
42 | |
43 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Order.Props memory) {
44 | * | Order.Props memory order;
45 | * | if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {
46 | | return order;
47 | | }
48 | |
49 | * | order.setAccount(dataStore.getAddress(
50 | * | keccak256(abi.encode(key, ACCOUNT))
51 | | ));
52 | |
53 | * | order.setReceiver(dataStore.getAddress(
54 | * | keccak256(abi.encode(key, RECEIVER))
55 | | ));
56 | |
57 | * | order.setCancellationReceiver(dataStore.getAddress(
58 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER))
59 | | ));
60 | |
61 | * | order.setCallbackContract(dataStore.getAddress(
62 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
63 | | ));
64 | |
65 | * | order.setUiFeeReceiver(dataStore.getAddress(
66 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
67 | | ));
68 | |
69 | * | order.setMarket(dataStore.getAddress(
70 | * | keccak256(abi.encode(key, MARKET))
71 | | ));
72 | |
73 | * | order.setInitialCollateralToken(dataStore.getAddress(
74 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))
75 | | ));
76 | |
77 | * | order.setSwapPath(dataStore.getAddressArray(
78 | * | keccak256(abi.encode(key, SWAP_PATH))
79 | | ));
80 | |
81 | * | order.setOrderType(Order.OrderType(dataStore.getUint(
82 | * | keccak256(abi.encode(key, ORDER_TYPE))
83 | | )));
84 | |
85 | * | order.setDecreasePositionSwapType(Order.DecreasePositionSwapType(dataStore.getUint(
86 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))
87 | | )));
88 | |
89 | * | order.setSizeDeltaUsd(dataStore.getUint(
90 | * | keccak256(abi.encode(key, SIZE_DELTA_USD))
91 | | ));
92 | |
93 | * | order.setInitialCollateralDeltaAmount(dataStore.getUint(
94 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))
95 | | ));
96 | |
97 | * | order.setTriggerPrice(dataStore.getUint(
98 | * | keccak256(abi.encode(key, TRIGGER_PRICE))
99 | | ));
100 | |
101 | * | order.setAcceptablePrice(dataStore.getUint(
102 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE))
103 | | ));
104 | |
105 | * | order.setExecutionFee(dataStore.getUint(
106 | * | keccak256(abi.encode(key, EXECUTION_FEE))
107 | | ));
108 | |
109 | * | order.setCallbackGasLimit(dataStore.getUint(
110 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
111 | | ));
112 | |
113 | * | order.setMinOutputAmount(dataStore.getUint(
114 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))
115 | | ));
116 | |
117 | * | order.setUpdatedAtBlock(dataStore.getUint(
118 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
119 | | ));
120 | |
121 | * | order.setUpdatedAtTime(dataStore.getUint(
122 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
123 | | ));
124 | |
125 | * | order.setIsLong(dataStore.getBool(
126 | * | keccak256(abi.encode(key, IS_LONG))
127 | | ));
128 | |
129 | * | order.setShouldUnwrapNativeToken(dataStore.getBool(
130 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
131 | | ));
132 | |
133 | * | order.setIsFrozen(dataStore.getBool(
134 | * | keccak256(abi.encode(key, IS_FROZEN))
135 | | ));
136 | |
137 | * | order.setAutoCancel(dataStore.getBool(
138 | * | keccak256(abi.encode(key, AUTO_CANCEL))
139 | | ));
140 | |
141 | * | return order;
142 | | }
143 | |
144 | * | function set(DataStore dataStore, bytes32 key, Order.Props memory order) internal {
145 | * | dataStore.addBytes32(
146 | | Keys.ORDER_LIST,
147 | * | key
148 | | );
149 | |
150 | * | dataStore.addBytes32(
151 | * | Keys.accountOrderListKey(order.account()),
152 | * | key
153 | | );
154 | |
155 | * | dataStore.setAddress(
156 | * | keccak256(abi.encode(key, ACCOUNT)),
157 | * | order.account()
158 | | );
159 | |
160 | * | dataStore.setAddress(
161 | * | keccak256(abi.encode(key, RECEIVER)),
162 | * | order.receiver()
163 | | );
164 | |
165 | * | dataStore.setAddress(
166 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER)),
167 | * | order.cancellationReceiver()
168 | | );
169 | |
170 | * | dataStore.setAddress(
171 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)),
172 | * | order.callbackContract()
173 | | );
174 | |
175 | * | dataStore.setAddress(
176 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)),
177 | * | order.uiFeeReceiver()
178 | | );
179 | |
180 | * | dataStore.setAddress(
181 | * | keccak256(abi.encode(key, MARKET)),
182 | * | order.market()
183 | | );
184 | |
185 | * | dataStore.setAddress(
186 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)),
187 | * | order.initialCollateralToken()
188 | | );
189 | |
190 | * | dataStore.setAddressArray(
191 | * | keccak256(abi.encode(key, SWAP_PATH)),
192 | * | order.swapPath()
193 | | );
194 | |
195 | * | dataStore.setUint(
196 | * | keccak256(abi.encode(key, ORDER_TYPE)),
197 | * | uint256(order.orderType())
198 | | );
199 | |
200 | * | dataStore.setUint(
201 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)),
202 | * | uint256(order.decreasePositionSwapType())
203 | | );
204 | |
205 | * | dataStore.setUint(
206 | * | keccak256(abi.encode(key, SIZE_DELTA_USD)),
207 | * | order.sizeDeltaUsd()
208 | | );
209 | |
210 | * | dataStore.setUint(
211 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)),
212 | * | order.initialCollateralDeltaAmount()
213 | | );
214 | |
215 | * | dataStore.setUint(
216 | * | keccak256(abi.encode(key, TRIGGER_PRICE)),
217 | * | order.triggerPrice()
218 | | );
219 | |
220 | * | dataStore.setUint(
221 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE)),
222 | * | order.acceptablePrice()
223 | | );
224 | |
225 | * | dataStore.setUint(
226 | * | keccak256(abi.encode(key, EXECUTION_FEE)),
227 | * | order.executionFee()
228 | | );
229 | |
230 | * | dataStore.setUint(
231 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
232 | * | order.callbackGasLimit()
233 | | );
234 | |
235 | * | dataStore.setUint(
236 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)),
237 | * | order.minOutputAmount()
238 | | );
239 | |
240 | * | dataStore.setUint(
241 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
242 | * | order.updatedAtBlock()
243 | | );
244 | |
245 | * | dataStore.setUint(
246 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)),
247 | * | order.updatedAtTime()
248 | | );
249 | |
250 | * | dataStore.setBool(
251 | * | keccak256(abi.encode(key, IS_LONG)),
252 | * | order.isLong()
253 | | );
254 | |
255 | * | dataStore.setBool(
256 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
257 | * | order.shouldUnwrapNativeToken()
258 | | );
259 | |
260 | * | dataStore.setBool(
261 | * | keccak256(abi.encode(key, IS_FROZEN)),
262 | * | order.isFrozen()
263 | | );
264 | |
265 | * | dataStore.setBool(
266 | * | keccak256(abi.encode(key, AUTO_CANCEL)),
267 | * | order.autoCancel()
268 | | );
269 | | }
270 | |
271 | * | function remove(DataStore dataStore, bytes32 key, address account) internal {
272 | * | if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {
273 | | revert Errors.OrderNotFound(key);
274 | | }
275 | |
276 | * | dataStore.removeBytes32(
277 | | Keys.ORDER_LIST,
278 | * | key
279 | | );
280 | |
281 | * | dataStore.removeBytes32(
282 | * | Keys.accountOrderListKey(account),
283 | * | key
284 | | );
285 | |
286 | * | dataStore.removeAddress(
287 | * | keccak256(abi.encode(key, ACCOUNT))
288 | | );
289 | |
290 | * | dataStore.removeAddress(
291 | * | keccak256(abi.encode(key, RECEIVER))
292 | | );
293 | |
294 | * | dataStore.removeAddress(
295 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER))
296 | | );
297 | |
298 | * | dataStore.removeAddress(
299 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
300 | | );
301 | |
302 | * | dataStore.removeAddress(
303 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
304 | | );
305 | |
306 | * | dataStore.removeAddress(
307 | * | keccak256(abi.encode(key, MARKET))
308 | | );
309 | |
310 | * | dataStore.removeAddress(
311 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))
312 | | );
313 | |
314 | * | dataStore.removeAddressArray(
315 | * | keccak256(abi.encode(key, SWAP_PATH))
316 | | );
317 | |
318 | * | dataStore.removeUint(
319 | * | keccak256(abi.encode(key, ORDER_TYPE))
320 | | );
321 | |
322 | * | dataStore.removeUint(
323 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))
324 | | );
325 | |
326 | * | dataStore.removeUint(
327 | * | keccak256(abi.encode(key, SIZE_DELTA_USD))
328 | | );
329 | |
330 | * | dataStore.removeUint(
331 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))
332 | | );
333 | |
334 | * | dataStore.removeUint(
335 | * | keccak256(abi.encode(key, TRIGGER_PRICE))
336 | | );
337 | |
338 | * | dataStore.removeUint(
339 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE))
340 | | );
341 | |
342 | * | dataStore.removeUint(
343 | * | keccak256(abi.encode(key, EXECUTION_FEE))
344 | | );
345 | |
346 | * | dataStore.removeUint(
347 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
348 | | );
349 | |
350 | * | dataStore.removeUint(
351 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))
352 | | );
353 | |
354 | * | dataStore.removeUint(
355 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
356 | | );
357 | |
358 | * | dataStore.removeUint(
359 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
360 | | );
361 | |
362 | * | dataStore.removeBool(
363 | * | keccak256(abi.encode(key, IS_LONG))
364 | | );
365 | |
366 | * | dataStore.removeBool(
367 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
368 | | );
369 | |
370 | * | dataStore.removeBool(
371 | * | keccak256(abi.encode(key, IS_FROZEN))
372 | | );
373 | |
374 | * | dataStore.removeBool(
375 | * | keccak256(abi.encode(key, AUTO_CANCEL))
376 | | );
377 | | }
378 | |
379 | | function getOrderCount(DataStore dataStore) internal view returns (uint256) {
380 | | return dataStore.getBytes32Count(Keys.ORDER_LIST);
381 | | }
382 | |
383 | | function getOrderKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
384 | | return dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end);
385 | | }
386 | |
387 | | function getAccountOrderCount(DataStore dataStore, address account) internal view returns (uint256) {
388 | | return dataStore.getBytes32Count(Keys.accountOrderListKey(account));
389 | | }
390 | |
391 | | function getAccountOrderKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
392 | | return dataStore.getBytes32ValuesAt(Keys.accountOrderListKey(account), start, end);
393 | | }
394 | | }
395 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./AutoCancelUtils.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../data/Keys.sol";
8 | |
9 | | import "./Order.sol";
10 | | import "./OrderVault.sol";
11 | | import "./OrderStoreUtils.sol";
12 | | import "./OrderEventUtils.sol";
13 | |
14 | | import "../nonce/NonceUtils.sol";
15 | | import "../oracle/Oracle.sol";
16 | | import "../oracle/OracleUtils.sol";
17 | | import "../event/EventEmitter.sol";
18 | |
19 | | import "./IncreaseOrderUtils.sol";
20 | | import "./DecreaseOrderUtils.sol";
21 | | import "./SwapOrderUtils.sol";
22 | | import "./BaseOrderUtils.sol";
23 | |
24 | | import "../swap/SwapUtils.sol";
25 | |
26 | | import "../gas/GasUtils.sol";
27 | | import "../callback/CallbackUtils.sol";
28 | |
29 | | import "../utils/Array.sol";
30 | | import "../utils/AccountUtils.sol";
31 | | import "../referral/ReferralUtils.sol";
32 | |
33 | | // @title OrderUtils
34 | | // @dev Library for order functions
35 | * | library OrderUtils {
36 | | using Order for Order.Props;
37 | | using Position for Position.Props;
38 | | using Price for Price.Props;
39 | | using Array for uint256[];
40 | |
41 | | struct CancelOrderParams {
42 | | DataStore dataStore;
43 | | EventEmitter eventEmitter;
44 | | OrderVault orderVault;
45 | | bytes32 key;
46 | | address keeper;
47 | | uint256 startingGas;
48 | | bool isExternalCall;
49 | | string reason;
50 | | bytes reasonBytes;
51 | | }
52 | |
53 | | // @dev creates an order in the order store
54 | | // @param dataStore DataStore
55 | | // @param eventEmitter EventEmitter
56 | | // @param orderVault OrderVault
57 | | // @param account the order account
58 | | // @param params IBaseOrderUtils.CreateOrderParams
59 | * | function createOrder(
60 | | DataStore dataStore,
61 | | EventEmitter eventEmitter,
62 | | OrderVault orderVault,
63 | | IReferralStorage referralStorage,
64 | | address account,
65 | | IBaseOrderUtils.CreateOrderParams memory params
66 | * | ) internal returns (bytes32) {
67 | * | AccountUtils.validateAccount(account);
68 | |
69 | * | ReferralUtils.setTraderReferralCode(referralStorage, account, params.referralCode);
70 | |
71 | * | uint256 initialCollateralDeltaAmount;
72 | |
73 | * | address wnt = TokenUtils.wnt(dataStore);
74 | |
75 | * | bool shouldRecordSeparateExecutionFeeTransfer = true;
76 | |
77 | * | if (
78 | * | params.orderType == Order.OrderType.MarketSwap ||
79 | * | params.orderType == Order.OrderType.LimitSwap ||
80 | * | params.orderType == Order.OrderType.MarketIncrease ||
81 | * | params.orderType == Order.OrderType.LimitIncrease
82 | | ) {
83 | | // for swaps and increase orders, the initialCollateralDeltaAmount is set based on the amount of tokens
84 | | // transferred to the orderVault
85 | * | initialCollateralDeltaAmount = orderVault.recordTransferIn(params.addresses.initialCollateralToken);
86 | * | if (params.addresses.initialCollateralToken == wnt) {
87 | * | if (initialCollateralDeltaAmount < params.numbers.executionFee) {
88 | | revert Errors.InsufficientWntAmountForExecutionFee(initialCollateralDeltaAmount, params.numbers.executionFee);
89 | | }
90 | * | initialCollateralDeltaAmount -= params.numbers.executionFee;
91 | * | shouldRecordSeparateExecutionFeeTransfer = false;
92 | | }
93 | * | } else if (
94 | * | params.orderType == Order.OrderType.MarketDecrease ||
95 | * | params.orderType == Order.OrderType.LimitDecrease ||
96 | * | params.orderType == Order.OrderType.StopLossDecrease
97 | | ) {
98 | | // for decrease orders, the initialCollateralDeltaAmount is based on the passed in value
99 | * | initialCollateralDeltaAmount = params.numbers.initialCollateralDeltaAmount;
100 | | } else {
101 | | revert Errors.OrderTypeCannotBeCreated(uint256(params.orderType));
102 | | }
103 | |
104 | * | if (shouldRecordSeparateExecutionFeeTransfer) {
105 | * | uint256 wntAmount = orderVault.recordTransferIn(wnt);
106 | * | if (wntAmount < params.numbers.executionFee) {
107 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.numbers.executionFee);
108 | | }
109 | |
110 | * | params.numbers.executionFee = wntAmount;
111 | | }
112 | |
113 | * | if (BaseOrderUtils.isPositionOrder(params.orderType)) {
114 | * | MarketUtils.validatePositionMarket(dataStore, params.addresses.market);
115 | | }
116 | |
117 | | // validate swap path markets
118 | * | MarketUtils.validateSwapPath(dataStore, params.addresses.swapPath);
119 | |
120 | * | Order.Props memory order;
121 | |
122 | * | order.setAccount(account);
123 | * | order.setReceiver(params.addresses.receiver);
124 | * | order.setCancellationReceiver(params.addresses.cancellationReceiver);
125 | * | order.setCallbackContract(params.addresses.callbackContract);
126 | * | order.setMarket(params.addresses.market);
127 | * | order.setInitialCollateralToken(params.addresses.initialCollateralToken);
128 | * | order.setUiFeeReceiver(params.addresses.uiFeeReceiver);
129 | * | order.setSwapPath(params.addresses.swapPath);
130 | * | order.setOrderType(params.orderType);
131 | * | order.setDecreasePositionSwapType(params.decreasePositionSwapType);
132 | * | order.setSizeDeltaUsd(params.numbers.sizeDeltaUsd);
133 | * | order.setInitialCollateralDeltaAmount(initialCollateralDeltaAmount);
134 | * | order.setTriggerPrice(params.numbers.triggerPrice);
135 | * | order.setAcceptablePrice(params.numbers.acceptablePrice);
136 | * | order.setExecutionFee(params.numbers.executionFee);
137 | * | order.setCallbackGasLimit(params.numbers.callbackGasLimit);
138 | * | order.setMinOutputAmount(params.numbers.minOutputAmount);
139 | * | order.setIsLong(params.isLong);
140 | * | order.setShouldUnwrapNativeToken(params.shouldUnwrapNativeToken);
141 | * | order.setAutoCancel(params.autoCancel);
142 | |
143 | * | AccountUtils.validateReceiver(order.receiver());
144 | |
145 | * | CallbackUtils.validateCallbackGasLimit(dataStore, order.callbackGasLimit());
146 | |
147 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order);
148 | * | uint256 oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(params.addresses.swapPath.length);
149 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, order.executionFee(), oraclePriceCount);
150 | |
151 | * | bytes32 key = NonceUtils.getNextKey(dataStore);
152 | |
153 | * | order.touch();
154 | |
155 | * | BaseOrderUtils.validateNonEmptyOrder(order);
156 | * | OrderStoreUtils.set(dataStore, key, order);
157 | |
158 | * | updateAutoCancelList(dataStore, key, order, order.autoCancel());
159 | * | validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order);
160 | |
161 | * | OrderEventUtils.emitOrderCreated(eventEmitter, key, order);
162 | |
163 | * | return key;
164 | | }
165 | |
166 | * | function cancelOrder(CancelOrderParams memory params) internal {
167 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
168 | * | if (params.isExternalCall) {
169 | * | params.startingGas -= gasleft() / 63;
170 | | }
171 | |
172 | * | Order.Props memory order = OrderStoreUtils.get(params.dataStore, params.key);
173 | * | BaseOrderUtils.validateNonEmptyOrder(order);
174 | |
175 | * | OrderStoreUtils.remove(params.dataStore, params.key, order.account());
176 | |
177 | * | if (BaseOrderUtils.isIncreaseOrder(order.orderType()) || BaseOrderUtils.isSwapOrder(order.orderType())) {
178 | * | if (order.initialCollateralDeltaAmount() > 0) {
179 | * | address cancellationReceiver = order.cancellationReceiver();
180 | * | if (cancellationReceiver == address(0)) {
181 | | cancellationReceiver = order.account();
182 | | }
183 | |
184 | * | params.orderVault.transferOut(
185 | * | order.initialCollateralToken(),
186 | * | cancellationReceiver,
187 | * | order.initialCollateralDeltaAmount(),
188 | * | order.shouldUnwrapNativeToken()
189 | | );
190 | | }
191 | | }
192 | |
193 | * | updateAutoCancelList(params.dataStore, params.key, order, false);
194 | |
195 | * | OrderEventUtils.emitOrderCancelled(
196 | * | params.eventEmitter,
197 | * | params.key,
198 | * | order.account(),
199 | * | params.reason,
200 | * | params.reasonBytes
201 | | );
202 | |
203 | * | address executionFeeReceiver = order.cancellationReceiver();
204 | |
205 | * | if (executionFeeReceiver == address(0)) {
206 | | executionFeeReceiver = order.receiver();
207 | | }
208 | |
209 | * | EventUtils.EventLogData memory eventData;
210 | * | CallbackUtils.afterOrderCancellation(params.key, order, eventData);
211 | |
212 | * | GasUtils.payExecutionFee(
213 | * | params.dataStore,
214 | * | params.eventEmitter,
215 | * | params.orderVault,
216 | * | params.key,
217 | * | order.callbackContract(),
218 | * | order.executionFee(),
219 | * | params.startingGas,
220 | * | GasUtils.estimateOrderOraclePriceCount(order.swapPath().length),
221 | * | params.keeper,
222 | * | executionFeeReceiver
223 | | );
224 | | }
225 | |
226 | | // @dev freezes an order
227 | | // @param dataStore DataStore
228 | | // @param eventEmitter EventEmitter
229 | | // @param orderVault OrderVault
230 | | // @param key the key of the order to freeze
231 | | // @param keeper the keeper sending the transaction
232 | | // @param startingGas the starting gas of the transaction
233 | | // @param reason the reason the order was frozen
234 | * | function freezeOrder(
235 | | DataStore dataStore,
236 | | EventEmitter eventEmitter,
237 | | OrderVault orderVault,
238 | | bytes32 key,
239 | | address keeper,
240 | | uint256 startingGas,
241 | | string memory reason,
242 | | bytes memory reasonBytes
243 | * | ) internal {
244 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
245 | * | startingGas -= gasleft() / 63;
246 | |
247 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
248 | * | BaseOrderUtils.validateNonEmptyOrder(order);
249 | |
250 | * | if (order.isFrozen()) {
251 | | revert Errors.OrderAlreadyFrozen();
252 | | }
253 | |
254 | * | order.setExecutionFee(0);
255 | * | order.setIsFrozen(true);
256 | * | OrderStoreUtils.set(dataStore, key, order);
257 | |
258 | * | OrderEventUtils.emitOrderFrozen(
259 | * | eventEmitter,
260 | * | key,
261 | * | order.account(),
262 | * | reason,
263 | * | reasonBytes
264 | | );
265 | |
266 | * | EventUtils.EventLogData memory eventData;
267 | * | CallbackUtils.afterOrderFrozen(key, order, eventData);
268 | |
269 | * | GasUtils.payExecutionFee(
270 | * | dataStore,
271 | * | eventEmitter,
272 | * | orderVault,
273 | * | key,
274 | * | order.callbackContract(),
275 | * | order.executionFee(),
276 | * | startingGas,
277 | * | GasUtils.estimateOrderOraclePriceCount(order.swapPath().length),
278 | * | keeper,
279 | * | order.receiver()
280 | | );
281 | | }
282 | |
283 | * | function clearAutoCancelOrders(
284 | | DataStore dataStore,
285 | | EventEmitter eventEmitter,
286 | | OrderVault orderVault,
287 | | bytes32 positionKey,
288 | | address keeper
289 | * | ) internal {
290 | * | bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey);
291 | |
292 | * | for (uint256 i; i < orderKeys.length; i++) {
293 | | cancelOrder(
294 | | CancelOrderParams(
295 | | dataStore,
296 | | eventEmitter,
297 | | orderVault,
298 | | orderKeys[i],
299 | | keeper, // keeper
300 | | gasleft(), // startingGas
301 | | false, // isExternalCall
302 | | "AUTO_CANCEL", // reason
303 | | "" // reasonBytes
304 | | )
305 | | );
306 | | }
307 | | }
308 | |
309 | * | function updateAutoCancelList(DataStore dataStore, bytes32 orderKey, Order.Props memory order, bool shouldAdd) internal {
310 | * | if (
311 | * | order.orderType() != Order.OrderType.LimitDecrease &&
312 | * | order.orderType() != Order.OrderType.StopLossDecrease
313 | | ) {
314 | * | return;
315 | | }
316 | |
317 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(order);
318 | |
319 | * | if (shouldAdd) {
320 | * | AutoCancelUtils.addAutoCancelOrderKey(dataStore, positionKey, orderKey);
321 | | } else {
322 | * | AutoCancelUtils.removeAutoCancelOrderKey(dataStore, positionKey, orderKey);
323 | | }
324 | | }
325 | |
326 | * | function validateTotalCallbackGasLimitForAutoCancelOrders(DataStore dataStore, Order.Props memory order) internal view {
327 | * | if (
328 | * | order.orderType() != Order.OrderType.LimitDecrease &&
329 | * | order.orderType() != Order.OrderType.StopLossDecrease
330 | | ) {
331 | * | return;
332 | | }
333 | |
334 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(order);
335 | * | uint256 maxTotal = dataStore.getUint(Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS);
336 | * | uint256 total = getTotalCallbackGasLimitForAutoCancelOrders(dataStore, positionKey);
337 | |
338 | * | if (total > maxTotal) {
339 | | revert Errors.MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(total, maxTotal);
340 | | }
341 | | }
342 | |
343 | * | function getTotalCallbackGasLimitForAutoCancelOrders(DataStore dataStore, bytes32 positionKey) internal view returns (uint256) {
344 | * | bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey);
345 | |
346 | * | uint256 total;
347 | |
348 | * | for (uint256 i; i < orderKeys.length; i++) {
349 | * | total += dataStore.getUint(
350 | * | keccak256(abi.encode(orderKeys[i], OrderStoreUtils.CALLBACK_GAS_LIMIT))
351 | | );
352 | | }
353 | |
354 | * | return total;
355 | | }
356 | | }
357 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderVault.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../bank/StrictBank.sol";
6 | |
7 | | // @title OrderVault
8 | | // @dev Vault for orders
9 | * | contract OrderVault is StrictBank {
10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/SwapOrderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseOrderUtils.sol";
6 | | import "../swap/SwapUtils.sol";
7 | | import "../order/OrderStoreUtils.sol";
8 | |
9 | | // @title SwapOrderUtils
10 | | // @dev Library for functions to help with processing a swap order
11 | * | library SwapOrderUtils {
12 | | using Order for Order.Props;
13 | | using Array for uint256[];
14 | |
15 | | using EventUtils for EventUtils.AddressItems;
16 | | using EventUtils for EventUtils.UintItems;
17 | | using EventUtils for EventUtils.IntItems;
18 | | using EventUtils for EventUtils.BoolItems;
19 | | using EventUtils for EventUtils.Bytes32Items;
20 | | using EventUtils for EventUtils.BytesItems;
21 | | using EventUtils for EventUtils.StringItems;
22 | |
23 | | // @dev process a swap order
24 | | // @param params BaseOrderUtils.ExecuteOrderParams
25 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) {
26 | * | if (params.order.market() != address(0)) {
27 | | revert Errors.UnexpectedMarket();
28 | | }
29 | |
30 | * | if (params.minOracleTimestamp < params.order.updatedAtTime()) {
31 | | revert Errors.OracleTimestampsAreSmallerThanRequired(
32 | | params.minOracleTimestamp,
33 | | params.order.updatedAtTime()
34 | | );
35 | | }
36 | |
37 | * | uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
38 | |
39 | * | if (
40 | * | params.order.orderType() == Order.OrderType.MarketSwap &&
41 | * | params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime
42 | | ) {
43 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
44 | * | params.maxOracleTimestamp,
45 | * | params.order.updatedAtTime(),
46 | * | requestExpirationTime
47 | | );
48 | | }
49 | |
50 | * | (address outputToken, uint256 outputAmount) = SwapUtils.swap(SwapUtils.SwapParams(
51 | * | params.contracts.dataStore,
52 | * | params.contracts.eventEmitter,
53 | * | params.contracts.oracle,
54 | * | params.contracts.orderVault,
55 | * | params.key,
56 | * | params.order.initialCollateralToken(),
57 | * | params.order.initialCollateralDeltaAmount(),
58 | * | params.swapPathMarkets,
59 | * | params.order.minOutputAmount(),
60 | * | params.order.receiver(),
61 | * | params.order.uiFeeReceiver(),
62 | * | params.order.shouldUnwrapNativeToken()
63 | | ));
64 | |
65 | * | EventUtils.EventLogData memory eventData;
66 | * | eventData.addressItems.initItems(1);
67 | * | eventData.addressItems.setItem(0, "outputToken", outputToken);
68 | * | eventData.uintItems.initItems(1);
69 | * | eventData.uintItems.setItem(0, "outputAmount", outputAmount);
70 | * | return eventData;
71 | | }
72 | | }
73 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionCollateralUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/Precision.sol";
6 | | import "../error/ErrorUtils.sol";
7 | |
8 | | import "../data/DataStore.sol";
9 | | import "../event/EventEmitter.sol";
10 | |
11 | | import "../oracle/Oracle.sol";
12 | | import "../pricing/PositionPricingUtils.sol";
13 | |
14 | | import "./Position.sol";
15 | | import "./PositionEventUtils.sol";
16 | | import "./PositionStoreUtils.sol";
17 | | import "./PositionUtils.sol";
18 | | import "../order/BaseOrderUtils.sol";
19 | | import "../order/OrderEventUtils.sol";
20 | |
21 | | import "../swap/SwapUtils.sol";
22 | | import "./DecreasePositionSwapUtils.sol";
23 | |
24 | | // @title DecreasePositionCollateralUtils
25 | | // @dev Library for functions to help with the calculations when decreasing a position
26 | * | library DecreasePositionCollateralUtils {
27 | | using SafeCast for uint256;
28 | | using SafeCast for int256;
29 | |
30 | | using Position for Position.Props;
31 | | using Order for Order.Props;
32 | | using Price for Price.Props;
33 | |
34 | | using EventUtils for EventUtils.AddressItems;
35 | | using EventUtils for EventUtils.UintItems;
36 | | using EventUtils for EventUtils.IntItems;
37 | | using EventUtils for EventUtils.BoolItems;
38 | | using EventUtils for EventUtils.Bytes32Items;
39 | | using EventUtils for EventUtils.BytesItems;
40 | | using EventUtils for EventUtils.StringItems;
41 | |
42 | | struct ProcessCollateralCache {
43 | | bool isInsolventCloseAllowed;
44 | | bool wasSwapped;
45 | | uint256 swapOutputAmount;
46 | | PayForCostResult result;
47 | | }
48 | |
49 | | struct PayForCostResult {
50 | | uint256 amountPaidInCollateralToken;
51 | | uint256 amountPaidInSecondaryOutputToken;
52 | | uint256 remainingCostUsd;
53 | | }
54 | |
55 | | // @dev handle the collateral changes of the position
56 | | // @param params PositionUtils.UpdatePositionParams
57 | | // @param cache DecreasePositionCache
58 | | // @return (PositionUtils.DecreasePositionCollateralValues, PositionPricingUtils.PositionFees)
59 | * | function processCollateral(
60 | | PositionUtils.UpdatePositionParams memory params,
61 | | PositionUtils.DecreasePositionCache memory cache
62 | | ) internal returns (
63 | * | PositionUtils.DecreasePositionCollateralValues memory,
64 | * | PositionPricingUtils.PositionFees memory
65 | | ) {
66 | * | ProcessCollateralCache memory collateralCache;
67 | * | PositionUtils.DecreasePositionCollateralValues memory values;
68 | |
69 | * | values.output.outputToken = params.position.collateralToken();
70 | * | values.output.secondaryOutputToken = cache.pnlToken;
71 | |
72 | | // only allow insolvent closing if it is a liquidation or ADL order
73 | | // isInsolventCloseAllowed is used in handleEarlyReturn to determine
74 | | // whether the txn should revert if the remainingCostUsd is below zero
75 | | //
76 | | // for isInsolventCloseAllowed to be true, the sizeDeltaUsd must equal
77 | | // the position size, otherwise there may be pending positive pnl that
78 | | // could be used to pay for fees and the position would be undercharged
79 | | // if the position is not fully closed
80 | | //
81 | | // for ADLs it may be possible that a position needs to be closed by a larger
82 | | // size to fully pay for fees, but closing by that larger size could cause a PnlOvercorrected
83 | | // error to be thrown in AdlHandler, this case should be rare
84 | * | collateralCache.isInsolventCloseAllowed =
85 | * | params.order.sizeDeltaUsd() == params.position.sizeInUsd() &&
86 | | (
87 | * | BaseOrderUtils.isLiquidationOrder(params.order.orderType()) ||
88 | * | params.secondaryOrderType == Order.SecondaryOrderType.Adl
89 | | );
90 | |
91 | | // in case price impact is too high it is capped and the difference is made to be claimable
92 | | // the execution price is based on the capped price impact so it may be a better price than what it should be
93 | | // priceImpactDiffUsd is the difference between the maximum price impact and the originally calculated price impact
94 | | // e.g. if the originally calculated price impact is -$100, but the capped price impact is -$80
95 | | // then priceImpactDiffUsd would be $20
96 | * | (values.priceImpactUsd, values.priceImpactDiffUsd, values.executionPrice) = PositionUtils.getExecutionPriceForDecrease(params, cache.prices.indexTokenPrice);
97 | |
98 | | // the totalPositionPnl is calculated based on the current indexTokenPrice instead of the executionPrice
99 | | // since the executionPrice factors in price impact which should be accounted for separately
100 | | // the sizeDeltaInTokens is calculated as position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd()
101 | | // the basePnlUsd is the pnl to be realized, and is calculated as:
102 | | // totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens()
103 | * | (values.basePnlUsd, values.uncappedBasePnlUsd, values.sizeDeltaInTokens) = PositionUtils.getPositionPnlUsd(
104 | * | params.contracts.dataStore,
105 | * | params.market,
106 | * | cache.prices,
107 | * | params.position,
108 | * | params.order.sizeDeltaUsd()
109 | | );
110 | |
111 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(
112 | * | params.contracts.dataStore, // dataStore
113 | * | params.contracts.referralStorage, // referralStorage
114 | * | params.position, // position
115 | * | cache.collateralTokenPrice, // collateralTokenPrice
116 | * | values.priceImpactUsd > 0, // forPositiveImpact
117 | * | params.market.longToken, // longToken
118 | * | params.market.shortToken, // shortToken
119 | * | params.order.sizeDeltaUsd(), // sizeDeltaUsd
120 | * | params.order.uiFeeReceiver() // uiFeeReceiver
121 | | );
122 | |
123 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(
124 | * | getPositionFeesParams
125 | | );
126 | |
127 | | // if the pnl is positive, deduct the pnl amount from the pool
128 | * | if (values.basePnlUsd > 0) {
129 | | // use pnlTokenPrice.max to minimize the tokens paid out
130 | * | uint256 deductionAmountForPool = values.basePnlUsd.toUint256() / cache.pnlTokenPrice.max;
131 | |
132 | * | MarketUtils.applyDeltaToPoolAmount(
133 | * | params.contracts.dataStore,
134 | * | params.contracts.eventEmitter,
135 | * | params.market,
136 | * | cache.pnlToken,
137 | * | -deductionAmountForPool.toInt256()
138 | | );
139 | |
140 | * | if (values.output.outputToken == cache.pnlToken) {
141 | * | values.output.outputAmount += deductionAmountForPool;
142 | | } else {
143 | * | values.output.secondaryOutputAmount += deductionAmountForPool;
144 | | }
145 | | }
146 | |
147 | * | if (values.priceImpactUsd > 0) {
148 | | // use indexTokenPrice.min to maximize the position impact pool reduction
149 | | uint256 deductionAmountForImpactPool = Calc.roundUpDivision(values.priceImpactUsd.toUint256(), cache.prices.indexTokenPrice.min);
150 | |
151 | | MarketUtils.applyDeltaToPositionImpactPool(
152 | | params.contracts.dataStore,
153 | | params.contracts.eventEmitter,
154 | | params.market.marketToken,
155 | | -deductionAmountForImpactPool.toInt256()
156 | | );
157 | |
158 | | // use pnlTokenPrice.max to minimize the payout from the pool
159 | | // some impact pool value may be transferred to the market token pool if there is a
160 | | // large spread between min and max prices
161 | | // since if there is a positive priceImpactUsd, the impact pool would be reduced using indexTokenPrice.min to
162 | | // maximize the deduction value, while the market token pool is reduced using the pnlTokenPrice.max to minimize
163 | | // the deduction value
164 | | // the pool value is calculated by subtracting the worth of the tokens in the position impact pool
165 | | // so this transfer of value would increase the price of the market token
166 | | uint256 deductionAmountForPool = values.priceImpactUsd.toUint256() / cache.pnlTokenPrice.max;
167 | |
168 | | MarketUtils.applyDeltaToPoolAmount(
169 | | params.contracts.dataStore,
170 | | params.contracts.eventEmitter,
171 | | params.market,
172 | | cache.pnlToken,
173 | | -deductionAmountForPool.toInt256()
174 | | );
175 | |
176 | | if (values.output.outputToken == cache.pnlToken) {
177 | | values.output.outputAmount += deductionAmountForPool;
178 | | } else {
179 | | values.output.secondaryOutputAmount += deductionAmountForPool;
180 | | }
181 | | }
182 | |
183 | | // swap profit to the collateral token
184 | | // if the decreasePositionSwapType was set to NoSwap or if the swap fails due
185 | | // to insufficient liquidity or other reasons then it is possible that
186 | | // the profit remains in a different token from the collateral token
187 | * | (collateralCache.wasSwapped, collateralCache.swapOutputAmount) = DecreasePositionSwapUtils.swapProfitToCollateralToken(
188 | * | params,
189 | * | cache.pnlToken,
190 | * | values.output.secondaryOutputAmount
191 | | );
192 | |
193 | | // if the swap was successful the profit should have been swapped
194 | | // to the collateral token
195 | * | if (collateralCache.wasSwapped) {
196 | * | values.output.outputAmount += collateralCache.swapOutputAmount;
197 | * | values.output.secondaryOutputAmount = 0;
198 | | }
199 | |
200 | * | values.remainingCollateralAmount = params.position.collateralAmount();
201 | |
202 | | // pay for funding fees
203 | * | (values, collateralCache.result) = payForCost(
204 | * | params,
205 | * | values,
206 | * | cache.prices,
207 | * | cache.collateralTokenPrice,
208 | | // use collateralTokenPrice.min because the payForCost
209 | | // will divide the USD value by the price.min as well
210 | * | fees.funding.fundingFeeAmount * cache.collateralTokenPrice.min
211 | | );
212 | |
213 | * | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {
214 | | address holdingAddress = params.contracts.dataStore.getAddress(Keys.HOLDING_ADDRESS);
215 | | if (holdingAddress == address(0)) {
216 | | revert Errors.EmptyHoldingAddress();
217 | | }
218 | |
219 | | // send the funding fee amount to the holding address
220 | | // this funding fee amount should be swapped to the required token
221 | | // and the resulting tokens should be deposited back into the pool
222 | | MarketUtils.incrementClaimableCollateralAmount(
223 | | params.contracts.dataStore,
224 | | params.contracts.eventEmitter,
225 | | params.market.marketToken,
226 | | values.output.secondaryOutputToken,
227 | | holdingAddress,
228 | | collateralCache.result.amountPaidInSecondaryOutputToken
229 | | );
230 | | }
231 | |
232 | * | if (collateralCache.result.amountPaidInCollateralToken < fees.funding.fundingFeeAmount) {
233 | | // the case where this is insufficient collateral to pay funding fees
234 | | // should be rare, and the difference should be small
235 | | // in case it happens, the pool should be topped up with the required amount using
236 | | // the claimable amount sent to the holding address, an insurance fund, or similar mechanism
237 | * | PositionEventUtils.emitInsufficientFundingFeePayment(
238 | * | params.contracts.eventEmitter,
239 | * | params.market.marketToken,
240 | * | params.position.collateralToken(),
241 | * | fees.funding.fundingFeeAmount,
242 | * | collateralCache.result.amountPaidInCollateralToken,
243 | * | collateralCache.result.amountPaidInSecondaryOutputToken
244 | | );
245 | | }
246 | |
247 | * | if (collateralCache.result.remainingCostUsd > 0) {
248 | * | return handleEarlyReturn(
249 | * | params,
250 | * | values,
251 | * | fees,
252 | * | collateralCache,
253 | | "funding"
254 | | );
255 | | }
256 | |
257 | | // pay for negative pnl
258 | * | if (values.basePnlUsd < 0) {
259 | * | (values, collateralCache.result) = payForCost(
260 | * | params,
261 | * | values,
262 | * | cache.prices,
263 | * | cache.collateralTokenPrice,
264 | * | (-values.basePnlUsd).toUint256()
265 | | );
266 | |
267 | * | if (collateralCache.result.amountPaidInCollateralToken > 0) {
268 | * | MarketUtils.applyDeltaToPoolAmount(
269 | * | params.contracts.dataStore,
270 | * | params.contracts.eventEmitter,
271 | * | params.market,
272 | * | params.position.collateralToken(),
273 | * | collateralCache.result.amountPaidInCollateralToken.toInt256()
274 | | );
275 | | }
276 | |
277 | * | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {
278 | | MarketUtils.applyDeltaToPoolAmount(
279 | | params.contracts.dataStore,
280 | | params.contracts.eventEmitter,
281 | | params.market,
282 | | values.output.secondaryOutputToken,
283 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()
284 | | );
285 | | }
286 | |
287 | * | if (collateralCache.result.remainingCostUsd > 0) {
288 | * | return handleEarlyReturn(
289 | * | params,
290 | * | values,
291 | * | fees,
292 | * | collateralCache,
293 | | "pnl"
294 | | );
295 | | }
296 | | }
297 | |
298 | | // pay for fees
299 | * | (values, collateralCache.result) = payForCost(
300 | * | params,
301 | * | values,
302 | * | cache.prices,
303 | * | cache.collateralTokenPrice,
304 | | // use collateralTokenPrice.min because the payForCost
305 | | // will divide the USD value by the price.min as well
306 | * | fees.totalCostAmountExcludingFunding * cache.collateralTokenPrice.min
307 | | );
308 | |
309 | | // if fees were fully paid in the collateral token, update the pool and claimable fee amounts
310 | * | if (collateralCache.result.remainingCostUsd == 0 && collateralCache.result.amountPaidInSecondaryOutputToken == 0) {
311 | | // there may be a large amount of borrowing fees that could have been accumulated
312 | | // these fees could cause the pool to become unbalanced, price impact is not paid for causing
313 | | // this imbalance
314 | | // the swap impact pool should be built up so that it can be used to pay for positive price impact
315 | | // for re-balancing to help handle this case
316 | * | MarketUtils.applyDeltaToPoolAmount(
317 | * | params.contracts.dataStore,
318 | * | params.contracts.eventEmitter,
319 | * | params.market,
320 | * | params.position.collateralToken(),
321 | * | fees.feeAmountForPool.toInt256()
322 | | );
323 | |
324 | * | FeeUtils.incrementClaimableFeeAmount(
325 | * | params.contracts.dataStore,
326 | * | params.contracts.eventEmitter,
327 | * | params.market.marketToken,
328 | * | params.position.collateralToken(),
329 | * | fees.feeReceiverAmount,
330 | | Keys.POSITION_FEE_TYPE
331 | | );
332 | |
333 | * | FeeUtils.incrementClaimableUiFeeAmount(
334 | * | params.contracts.dataStore,
335 | * | params.contracts.eventEmitter,
336 | * | params.order.uiFeeReceiver(),
337 | * | params.market.marketToken,
338 | * | params.position.collateralToken(),
339 | * | fees.ui.uiFeeAmount,
340 | | Keys.UI_POSITION_FEE_TYPE
341 | | );
342 | | } else {
343 | | // the fees are expected to be paid in the collateral token
344 | | // if there are insufficient funds to pay for fees entirely in the collateral token
345 | | // then credit the fee amount entirely to the pool
346 | | if (collateralCache.result.amountPaidInCollateralToken > 0) {
347 | | MarketUtils.applyDeltaToPoolAmount(
348 | | params.contracts.dataStore,
349 | | params.contracts.eventEmitter,
350 | | params.market,
351 | | params.position.collateralToken(),
352 | | collateralCache.result.amountPaidInCollateralToken.toInt256()
353 | | );
354 | | }
355 | |
356 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {
357 | | MarketUtils.applyDeltaToPoolAmount(
358 | | params.contracts.dataStore,
359 | | params.contracts.eventEmitter,
360 | | params.market,
361 | | values.output.secondaryOutputToken,
362 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()
363 | | );
364 | | }
365 | |
366 | | // empty the fees since the amount was entirely paid to the pool instead of for fees
367 | | // it is possible for the txn execution to still complete even in this case
368 | | // as long as the remainingCostUsd is still zero
369 | | fees = getEmptyFees(fees);
370 | | }
371 | |
372 | * | if (collateralCache.result.remainingCostUsd > 0) {
373 | | return handleEarlyReturn(
374 | | params,
375 | | values,
376 | | fees,
377 | | collateralCache,
378 | | "fees"
379 | | );
380 | | }
381 | |
382 | | // pay for negative price impact
383 | * | if (values.priceImpactUsd < 0) {
384 | | (values, collateralCache.result) = payForCost(
385 | | params,
386 | | values,
387 | | cache.prices,
388 | | cache.collateralTokenPrice,
389 | | (-values.priceImpactUsd).toUint256()
390 | | );
391 | |
392 | | if (collateralCache.result.amountPaidInCollateralToken > 0) {
393 | | MarketUtils.applyDeltaToPoolAmount(
394 | | params.contracts.dataStore,
395 | | params.contracts.eventEmitter,
396 | | params.market,
397 | | params.position.collateralToken(),
398 | | collateralCache.result.amountPaidInCollateralToken.toInt256()
399 | | );
400 | |
401 | | MarketUtils.applyDeltaToPositionImpactPool(
402 | | params.contracts.dataStore,
403 | | params.contracts.eventEmitter,
404 | | params.market.marketToken,
405 | | (collateralCache.result.amountPaidInCollateralToken * cache.collateralTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256()
406 | | );
407 | | }
408 | |
409 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {
410 | | MarketUtils.applyDeltaToPoolAmount(
411 | | params.contracts.dataStore,
412 | | params.contracts.eventEmitter,
413 | | params.market,
414 | | values.output.secondaryOutputToken,
415 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256()
416 | | );
417 | |
418 | | MarketUtils.applyDeltaToPositionImpactPool(
419 | | params.contracts.dataStore,
420 | | params.contracts.eventEmitter,
421 | | params.market.marketToken,
422 | | (collateralCache.result.amountPaidInSecondaryOutputToken * cache.pnlTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256()
423 | | );
424 | | }
425 | |
426 | | if (collateralCache.result.remainingCostUsd > 0) {
427 | | return handleEarlyReturn(
428 | | params,
429 | | values,
430 | | fees,
431 | | collateralCache,
432 | | "impact"
433 | | );
434 | | }
435 | | }
436 | |
437 | | // pay for price impact diff
438 | * | if (values.priceImpactDiffUsd > 0) {
439 | | (values, collateralCache.result) = payForCost(
440 | | params,
441 | | values,
442 | | cache.prices,
443 | | cache.collateralTokenPrice,
444 | | values.priceImpactDiffUsd
445 | | );
446 | |
447 | | if (collateralCache.result.amountPaidInCollateralToken > 0) {
448 | | MarketUtils.incrementClaimableCollateralAmount(
449 | | params.contracts.dataStore,
450 | | params.contracts.eventEmitter,
451 | | params.market.marketToken,
452 | | params.position.collateralToken(),
453 | | params.order.account(),
454 | | collateralCache.result.amountPaidInCollateralToken
455 | | );
456 | | }
457 | |
458 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) {
459 | | MarketUtils.incrementClaimableCollateralAmount(
460 | | params.contracts.dataStore,
461 | | params.contracts.eventEmitter,
462 | | params.market.marketToken,
463 | | values.output.secondaryOutputToken,
464 | | params.order.account(),
465 | | collateralCache.result.amountPaidInSecondaryOutputToken
466 | | );
467 | | }
468 | |
469 | | if (collateralCache.result.remainingCostUsd > 0) {
470 | | return handleEarlyReturn(
471 | | params,
472 | | values,
473 | | fees,
474 | | collateralCache,
475 | | "diff"
476 | | );
477 | | }
478 | | }
479 | |
480 | | // the priceImpactDiffUsd has been deducted from the output amount or the position's collateral
481 | | // to reduce the chance that the position's collateral is reduced by an unexpected amount, adjust the
482 | | // initialCollateralDeltaAmount by the priceImpactDiffAmount
483 | | // this would also help to prevent the position's leverage from being unexpectedly increased
484 | | //
485 | | // note that this calculation may not be entirely accurate since it is possible that the priceImpactDiffUsd
486 | | // could have been paid with one of or a combination of collateral / outputAmount / secondaryOutputAmount
487 | * | if (params.order.initialCollateralDeltaAmount() > 0 && values.priceImpactDiffUsd > 0) {
488 | | uint256 initialCollateralDeltaAmount = params.order.initialCollateralDeltaAmount();
489 | |
490 | | uint256 priceImpactDiffAmount = values.priceImpactDiffUsd / cache.collateralTokenPrice.min;
491 | | if (initialCollateralDeltaAmount > priceImpactDiffAmount) {
492 | | params.order.setInitialCollateralDeltaAmount(initialCollateralDeltaAmount - priceImpactDiffAmount);
493 | | } else {
494 | | params.order.setInitialCollateralDeltaAmount(0);
495 | | }
496 | |
497 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(
498 | | params.contracts.eventEmitter,
499 | | params.orderKey,
500 | | initialCollateralDeltaAmount, // collateralDeltaAmount
501 | | params.order.initialCollateralDeltaAmount() // nextCollateralDeltaAmount
502 | | );
503 | | }
504 | |
505 | | // cap the withdrawable amount to the remainingCollateralAmount
506 | * | if (params.order.initialCollateralDeltaAmount() > values.remainingCollateralAmount) {
507 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(
508 | | params.contracts.eventEmitter,
509 | | params.orderKey,
510 | | params.order.initialCollateralDeltaAmount(), // collateralDeltaAmount
511 | | values.remainingCollateralAmount // nextCollateralDeltaAmount
512 | | );
513 | |
514 | | params.order.setInitialCollateralDeltaAmount(values.remainingCollateralAmount);
515 | | }
516 | |
517 | * | if (params.order.initialCollateralDeltaAmount() > 0) {
518 | * | values.remainingCollateralAmount -= params.order.initialCollateralDeltaAmount();
519 | * | values.output.outputAmount += params.order.initialCollateralDeltaAmount();
520 | | }
521 | |
522 | * | return (values, fees);
523 | | }
524 | |
525 | * | function payForCost(
526 | | PositionUtils.UpdatePositionParams memory params,
527 | | PositionUtils.DecreasePositionCollateralValues memory values,
528 | | MarketUtils.MarketPrices memory prices,
529 | | Price.Props memory collateralTokenPrice,
530 | | uint256 costUsd
531 | * | ) internal pure returns (PositionUtils.DecreasePositionCollateralValues memory, PayForCostResult memory) {
532 | * | PayForCostResult memory result;
533 | |
534 | * | if (costUsd == 0) { return (values, result); }
535 | |
536 | * | uint256 remainingCostInOutputToken = Calc.roundUpDivision(costUsd, collateralTokenPrice.min);
537 | |
538 | * | if (values.output.outputAmount > 0) {
539 | * | if (values.output.outputAmount > remainingCostInOutputToken) {
540 | * | result.amountPaidInCollateralToken += remainingCostInOutputToken;
541 | * | values.output.outputAmount -= remainingCostInOutputToken;
542 | * | remainingCostInOutputToken = 0;
543 | | } else {
544 | * | result.amountPaidInCollateralToken += values.output.outputAmount;
545 | * | remainingCostInOutputToken -= values.output.outputAmount;
546 | * | values.output.outputAmount = 0;
547 | | }
548 | | }
549 | |
550 | * | if (remainingCostInOutputToken == 0) { return (values, result); }
551 | |
552 | * | if (values.remainingCollateralAmount > 0) {
553 | * | if (values.remainingCollateralAmount > remainingCostInOutputToken) {
554 | * | result.amountPaidInCollateralToken += remainingCostInOutputToken;
555 | * | values.remainingCollateralAmount -= remainingCostInOutputToken;
556 | * | remainingCostInOutputToken = 0;
557 | | } else {
558 | * | result.amountPaidInCollateralToken += values.remainingCollateralAmount;
559 | * | remainingCostInOutputToken -= values.remainingCollateralAmount;
560 | * | values.remainingCollateralAmount = 0;
561 | | }
562 | | }
563 | |
564 | * | if (remainingCostInOutputToken == 0) { return (values, result); }
565 | |
566 | * | Price.Props memory secondaryOutputTokenPrice = MarketUtils.getCachedTokenPrice(values.output.secondaryOutputToken, params.market, prices);
567 | |
568 | * | uint256 remainingCostInSecondaryOutputToken = remainingCostInOutputToken * collateralTokenPrice.min / secondaryOutputTokenPrice.min;
569 | |
570 | * | if (values.output.secondaryOutputAmount > 0) {
571 | | if (values.output.secondaryOutputAmount > remainingCostInSecondaryOutputToken) {
572 | | result.amountPaidInSecondaryOutputToken += remainingCostInSecondaryOutputToken;
573 | | values.output.secondaryOutputAmount -= remainingCostInSecondaryOutputToken;
574 | | remainingCostInSecondaryOutputToken = 0;
575 | | } else {
576 | | result.amountPaidInSecondaryOutputToken += values.output.secondaryOutputAmount;
577 | | remainingCostInSecondaryOutputToken -= values.output.secondaryOutputAmount;
578 | | values.output.secondaryOutputAmount = 0;
579 | | }
580 | | }
581 | |
582 | * | result.remainingCostUsd = remainingCostInSecondaryOutputToken * secondaryOutputTokenPrice.min;
583 | |
584 | * | return (values, result);
585 | | }
586 | |
587 | * | function handleEarlyReturn(
588 | | PositionUtils.UpdatePositionParams memory params,
589 | | PositionUtils.DecreasePositionCollateralValues memory values,
590 | | PositionPricingUtils.PositionFees memory fees,
591 | | ProcessCollateralCache memory collateralCache,
592 | | string memory step
593 | * | ) internal returns (PositionUtils.DecreasePositionCollateralValues memory, PositionPricingUtils.PositionFees memory) {
594 | * | if (!collateralCache.isInsolventCloseAllowed) {
595 | * | revert Errors.InsufficientFundsToPayForCosts(collateralCache.result.remainingCostUsd, step);
596 | | }
597 | |
598 | * | PositionEventUtils.emitPositionFeesInfo(
599 | * | params.contracts.eventEmitter,
600 | * | params.orderKey,
601 | * | params.positionKey,
602 | * | params.market.marketToken,
603 | * | params.position.collateralToken(),
604 | * | params.order.sizeDeltaUsd(),
605 | * | false, // isIncrease
606 | * | fees
607 | | );
608 | |
609 | * | PositionEventUtils.emitInsolventCloseInfo(
610 | * | params.contracts.eventEmitter,
611 | * | params.orderKey,
612 | * | params.position.collateralAmount(),
613 | * | values.basePnlUsd,
614 | * | collateralCache.result.remainingCostUsd,
615 | * | step
616 | | );
617 | |
618 | * | return (values, getEmptyFees(fees));
619 | | }
620 | |
621 | * | function getEmptyFees(
622 | | PositionPricingUtils.PositionFees memory fees
623 | * | ) internal pure returns (PositionPricingUtils.PositionFees memory) {
624 | * | PositionPricingUtils.PositionReferralFees memory referral = PositionPricingUtils.PositionReferralFees(
625 | * | bytes32(0), // referralCode
626 | * | address(0), // affiliate
627 | * | address(0), // trader
628 | * | 0, // totalRebateFactor
629 | * | 0, // traderDiscountFactor
630 | * | 0, // totalRebateAmount
631 | * | 0, // traderDiscountAmount
632 | * | 0 // affiliateRewardAmount
633 | | );
634 | |
635 | | // allow the accumulated funding fees to still be claimable
636 | | // return the latestFundingFeeAmountPerSize, latestLongTokenClaimableFundingAmountPerSize,
637 | | // latestShortTokenClaimableFundingAmountPerSize values as these may be used to update the
638 | | // position's values if the position will be partially closed
639 | * | PositionPricingUtils.PositionFundingFees memory funding = PositionPricingUtils.PositionFundingFees(
640 | * | 0, // fundingFeeAmount
641 | * | fees.funding.claimableLongTokenAmount, // claimableLongTokenAmount
642 | * | fees.funding.claimableShortTokenAmount, // claimableShortTokenAmount
643 | * | fees.funding.latestFundingFeeAmountPerSize, // latestFundingFeeAmountPerSize
644 | * | fees.funding.latestLongTokenClaimableFundingAmountPerSize, // latestLongTokenClaimableFundingAmountPerSize
645 | * | fees.funding.latestShortTokenClaimableFundingAmountPerSize // latestShortTokenClaimableFundingAmountPerSize
646 | | );
647 | |
648 | * | PositionPricingUtils.PositionBorrowingFees memory borrowing = PositionPricingUtils.PositionBorrowingFees(
649 | * | 0, // borrowingFeeUsd
650 | * | 0, // borrowingFeeAmount
651 | * | 0, // borrowingFeeReceiverFactor
652 | * | 0 // borrowingFeeAmountForFeeReceiver
653 | | );
654 | |
655 | * | PositionPricingUtils.PositionUiFees memory ui = PositionPricingUtils.PositionUiFees(
656 | * | address(0), // uiFeeReceiver
657 | * | 0, // uiFeeReceiverFactor
658 | * | 0 // uiFeeAmount
659 | | );
660 | |
661 | | // all fees are zeroed even though funding may have been paid
662 | | // the funding fee amount value may not be accurate in the events due to this
663 | * | PositionPricingUtils.PositionFees memory _fees = PositionPricingUtils.PositionFees(
664 | * | referral, // referral
665 | * | funding, // funding
666 | * | borrowing, // borrowing
667 | * | ui, // ui
668 | * | fees.collateralTokenPrice, // collateralTokenPrice
669 | * | 0, // positionFeeFactor
670 | * | 0, // protocolFeeAmount
671 | * | 0, // positionFeeReceiverFactor
672 | * | 0, // feeReceiverAmount
673 | * | 0, // feeAmountForPool
674 | * | 0, // positionFeeAmountForPool
675 | * | 0, // positionFeeAmount
676 | * | 0, // totalCostAmountExcludingFunding
677 | * | 0 // totalCostAmount
678 | | );
679 | |
680 | * | return _fees;
681 | | }
682 | | }
683 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionSwapUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./PositionUtils.sol";
6 | |
7 | * | library DecreasePositionSwapUtils {
8 | | using Order for Order.Props;
9 | | using Position for Position.Props;
10 | |
11 | | // swap the withdrawn collateral from collateralToken to pnlToken if needed
12 | * | function swapWithdrawnCollateralToPnlToken(
13 | | PositionUtils.UpdatePositionParams memory params,
14 | | PositionUtils.DecreasePositionCollateralValues memory values
15 | * | ) internal returns (PositionUtils.DecreasePositionCollateralValues memory) {
16 | * | if (values.output.outputAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken) {
17 | | Market.Props[] memory swapPathMarkets = new Market.Props[](1);
18 | | swapPathMarkets[0] = params.market;
19 | |
20 | | try params.contracts.swapHandler.swap(
21 | | SwapUtils.SwapParams(
22 | | params.contracts.dataStore,
23 | | params.contracts.eventEmitter,
24 | | params.contracts.oracle,
25 | | Bank(payable(params.market.marketToken)),
26 | | params.orderKey,
27 | | params.position.collateralToken(), // tokenIn
28 | | values.output.outputAmount, // amountIn
29 | | swapPathMarkets, // markets
30 | | 0, // minOutputAmount
31 | | params.market.marketToken, // receiver
32 | | params.order.uiFeeReceiver(), // uiFeeReceiver
33 | | false // shouldUnwrapNativeToken
34 | | )
35 | | ) returns (address tokenOut, uint256 swapOutputAmount) {
36 | | if (tokenOut != values.output.secondaryOutputToken) {
37 | | revert Errors.InvalidOutputToken(tokenOut, values.output.secondaryOutputToken);
38 | | }
39 | | // combine the values into outputToken and outputAmount
40 | | values.output.outputToken = tokenOut;
41 | | values.output.outputAmount = values.output.secondaryOutputAmount + swapOutputAmount;
42 | | values.output.secondaryOutputAmount = 0;
43 | | } catch Error(string memory reason) {
44 | | emit SwapUtils.SwapReverted(reason, "");
45 | | } catch (bytes memory reasonBytes) {
46 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
47 | | emit SwapUtils.SwapReverted(reason, reasonBytes);
48 | | }
49 | | }
50 | |
51 | * | return values;
52 | | }
53 | |
54 | | // swap the realized profit from the pnlToken to the collateralToken if needed
55 | * | function swapProfitToCollateralToken(
56 | | PositionUtils.UpdatePositionParams memory params,
57 | | address pnlToken,
58 | | uint256 profitAmount
59 | * | ) internal returns (bool, uint256) {
60 | * | if (profitAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken) {
61 | * | Market.Props[] memory swapPathMarkets = new Market.Props[](1);
62 | * | swapPathMarkets[0] = params.market;
63 | |
64 | * | try params.contracts.swapHandler.swap(
65 | * | SwapUtils.SwapParams(
66 | * | params.contracts.dataStore,
67 | * | params.contracts.eventEmitter,
68 | * | params.contracts.oracle,
69 | * | Bank(payable(params.market.marketToken)),
70 | * | params.orderKey,
71 | * | pnlToken, // tokenIn
72 | * | profitAmount, // amountIn
73 | * | swapPathMarkets, // markets
74 | * | 0, // minOutputAmount
75 | * | params.market.marketToken, // receiver
76 | * | params.order.uiFeeReceiver(), // uiFeeReceiver
77 | * | false // shouldUnwrapNativeToken
78 | | )
79 | | ) returns (address /* tokenOut */, uint256 swapOutputAmount) {
80 | * | return (true, swapOutputAmount);
81 | | } catch Error(string memory reason) {
82 | | emit SwapUtils.SwapReverted(reason, "");
83 | * | } catch (bytes memory reasonBytes) {
84 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
85 | * | emit SwapUtils.SwapReverted(reason, reasonBytes);
86 | | }
87 | | }
88 | |
89 | * | return (false, 0);
90 | | }
91 | | }
92 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/Precision.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../event/EventEmitter.sol";
9 | |
10 | | import "../oracle/Oracle.sol";
11 | | import "../pricing/PositionPricingUtils.sol";
12 | |
13 | | import "./Position.sol";
14 | | import "./PositionStoreUtils.sol";
15 | | import "./PositionUtils.sol";
16 | | import "./PositionEventUtils.sol";
17 | | import "../order/BaseOrderUtils.sol";
18 | | import "../order/OrderEventUtils.sol";
19 | |
20 | | import "./DecreasePositionCollateralUtils.sol";
21 | |
22 | | // @title DecreasePositionUtils
23 | | // @dev Library for functions to help with decreasing a position
24 | * | library DecreasePositionUtils {
25 | | using SafeCast for uint256;
26 | | using SafeCast for int256;
27 | |
28 | | using Position for Position.Props;
29 | | using Order for Order.Props;
30 | | using Price for Price.Props;
31 | |
32 | | // @dev DecreasePositionResult struct for the results of decreasePosition
33 | | // @param outputToken the output token
34 | | // @param outputAmount the output amount
35 | | // @param secondaryOutputToken the secondary output token
36 | | // @param secondaryOutputAmount the secondary output amount
37 | | struct DecreasePositionResult {
38 | | address outputToken;
39 | | uint256 outputAmount;
40 | | address secondaryOutputToken;
41 | | uint256 secondaryOutputAmount;
42 | | uint256 orderSizeDeltaUsd;
43 | | uint256 orderInitialCollateralDeltaAmount;
44 | | }
45 | |
46 | | // @dev decreases a position
47 | | // The decreasePosition function decreases the size of an existing position
48 | | // in a market. It takes a PositionUtils.UpdatePositionParams object as an input, which
49 | | // includes information about the position to be decreased, the market in
50 | | // which the position exists, and the order that is being used to decrease the position.
51 | | //
52 | | // The function first calculates the prices of the tokens in the market, and then
53 | | // checks whether the position is liquidatable based on the current market prices.
54 | | // If the order is a liquidation order and the position is not liquidatable, the function reverts.
55 | | //
56 | | // If there is not enough collateral in the position to complete the decrease,
57 | | // the function reverts. Otherwise, the function updates the position's size and
58 | | // collateral amount, and increments the claimable funding amount for
59 | | // the market if necessary.
60 | | //
61 | | // Finally, the function returns a DecreasePositionResult object containing
62 | | // information about the outcome of the decrease operation, including the amount
63 | | // of collateral removed from the position and any fees that were paid.
64 | | // @param params PositionUtils.UpdatePositionParams
65 | * | function decreasePosition(
66 | | PositionUtils.UpdatePositionParams memory params
67 | * | ) internal returns (DecreasePositionResult memory) {
68 | * | PositionUtils.DecreasePositionCache memory cache;
69 | |
70 | * | cache.prices = MarketUtils.getMarketPrices(
71 | * | params.contracts.oracle,
72 | * | params.market
73 | | );
74 | |
75 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(
76 | * | params.order.initialCollateralToken(),
77 | * | params.market,
78 | * | cache.prices
79 | | );
80 | |
81 | | // cap the order size to the position size
82 | * | if (params.order.sizeDeltaUsd() > params.position.sizeInUsd()) {
83 | * | if (params.order.orderType() == Order.OrderType.LimitDecrease ||
84 | * | params.order.orderType() == Order.OrderType.StopLossDecrease) {
85 | |
86 | | OrderEventUtils.emitOrderSizeDeltaAutoUpdated(
87 | | params.contracts.eventEmitter,
88 | | params.orderKey,
89 | | params.order.sizeDeltaUsd(),
90 | | params.position.sizeInUsd()
91 | | );
92 | |
93 | | params.order.setSizeDeltaUsd(params.position.sizeInUsd());
94 | | } else {
95 | * | revert Errors.InvalidDecreaseOrderSize(params.order.sizeDeltaUsd(), params.position.sizeInUsd());
96 | | }
97 | | }
98 | |
99 | | // cap the initialCollateralDeltaAmount to the position collateralAmount
100 | * | if (params.order.initialCollateralDeltaAmount() > params.position.collateralAmount()) {
101 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(
102 | | params.contracts.eventEmitter,
103 | | params.orderKey,
104 | | params.order.initialCollateralDeltaAmount(),
105 | | params.position.collateralAmount()
106 | | );
107 | |
108 | | params.order.setInitialCollateralDeltaAmount(params.position.collateralAmount());
109 | | }
110 | |
111 | | // if the position will be partially decreased then do a check on the
112 | | // remaining collateral amount and update the order attributes if needed
113 | * | if (params.order.sizeDeltaUsd() < params.position.sizeInUsd()) {
114 | | // estimate pnl based on indexTokenPrice
115 | * | (cache.estimatedPositionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd(
116 | * | params.contracts.dataStore,
117 | * | params.market,
118 | * | cache.prices,
119 | * | params.position,
120 | * | params.position.sizeInUsd()
121 | | );
122 | |
123 | * | cache.estimatedRealizedPnlUsd = Precision.mulDiv(cache.estimatedPositionPnlUsd, params.order.sizeDeltaUsd(), params.position.sizeInUsd());
124 | * | cache.estimatedRemainingPnlUsd = cache.estimatedPositionPnlUsd - cache.estimatedRealizedPnlUsd;
125 | |
126 | * | PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues(
127 | * | params.position.sizeInUsd() - params.order.sizeDeltaUsd(), // positionSizeInUsd
128 | * | params.position.collateralAmount() - params.order.initialCollateralDeltaAmount(), // positionCollateralAmount
129 | * | cache.estimatedRealizedPnlUsd, // realizedPnlUsd
130 | * | -params.order.sizeDeltaUsd().toInt256() // openInterestDelta
131 | | );
132 | |
133 | * | (bool willBeSufficient, int256 estimatedRemainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient(
134 | * | params.contracts.dataStore,
135 | * | params.market,
136 | * | cache.prices,
137 | * | params.position.collateralToken(),
138 | * | params.position.isLong(),
139 | * | positionValues
140 | | );
141 | |
142 | | // do not allow withdrawal of collateral if it would lead to the position
143 | | // having an insufficient amount of collateral
144 | | // this helps to prevent gaming by opening a position then reducing collateral
145 | | // to increase the leverage of the position
146 | * | if (!willBeSufficient) {
147 | * | if (params.order.sizeDeltaUsd() == 0) {
148 | | revert Errors.UnableToWithdrawCollateral(estimatedRemainingCollateralUsd);
149 | | }
150 | |
151 | * | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated(
152 | * | params.contracts.eventEmitter,
153 | * | params.orderKey,
154 | * | params.order.initialCollateralDeltaAmount(),
155 | * | 0
156 | | );
157 | |
158 | | // the estimatedRemainingCollateralUsd subtracts the initialCollateralDeltaAmount
159 | | // since the initialCollateralDeltaAmount will be set to zero, the initialCollateralDeltaAmount
160 | | // should be added back to the estimatedRemainingCollateralUsd
161 | * | estimatedRemainingCollateralUsd += (params.order.initialCollateralDeltaAmount() * cache.collateralTokenPrice.min).toInt256();
162 | * | params.order.setInitialCollateralDeltaAmount(0);
163 | | }
164 | |
165 | | // if the remaining collateral including position pnl will be below
166 | | // the min collateral usd value, then close the position
167 | | //
168 | | // if the position has sufficient remaining collateral including pnl
169 | | // then allow the position to be partially closed and the updated
170 | | // position to remain open
171 | * | if ((estimatedRemainingCollateralUsd + cache.estimatedRemainingPnlUsd) < params.contracts.dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256()) {
172 | * | OrderEventUtils.emitOrderSizeDeltaAutoUpdated(
173 | * | params.contracts.eventEmitter,
174 | * | params.orderKey,
175 | * | params.order.sizeDeltaUsd(),
176 | * | params.position.sizeInUsd()
177 | | );
178 | |
179 | * | params.order.setSizeDeltaUsd(params.position.sizeInUsd());
180 | | }
181 | |
182 | * | if (
183 | * | params.position.sizeInUsd() > params.order.sizeDeltaUsd() &&
184 | * | params.position.sizeInUsd() - params.order.sizeDeltaUsd() < params.contracts.dataStore.getUint(Keys.MIN_POSITION_SIZE_USD)
185 | | ) {
186 | | OrderEventUtils.emitOrderSizeDeltaAutoUpdated(
187 | | params.contracts.eventEmitter,
188 | | params.orderKey,
189 | | params.order.sizeDeltaUsd(),
190 | | params.position.sizeInUsd()
191 | | );
192 | |
193 | | params.order.setSizeDeltaUsd(params.position.sizeInUsd());
194 | | }
195 | | }
196 | |
197 | | // if the position will be closed, set the initial collateral delta amount
198 | | // to zero to help ensure that the order can be executed
199 | * | if (params.order.sizeDeltaUsd() == params.position.sizeInUsd() && params.order.initialCollateralDeltaAmount() > 0) {
200 | * | params.order.setInitialCollateralDeltaAmount(0);
201 | | }
202 | |
203 | * | cache.pnlToken = params.position.isLong() ? params.market.longToken : params.market.shortToken;
204 | * | cache.pnlTokenPrice = params.position.isLong() ? cache.prices.longTokenPrice : cache.prices.shortTokenPrice;
205 | |
206 | * | if (params.order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap &&
207 | * | cache.pnlToken == params.position.collateralToken()) {
208 | * | params.order.setDecreasePositionSwapType(Order.DecreasePositionSwapType.NoSwap);
209 | | }
210 | |
211 | * | if (BaseOrderUtils.isLiquidationOrder(params.order.orderType())) {
212 | * | (bool isLiquidatable, string memory reason, PositionUtils.IsPositionLiquidatableInfo memory info) = PositionUtils.isPositionLiquidatable(
213 | * | params.contracts.dataStore,
214 | * | params.contracts.referralStorage,
215 | * | params.position,
216 | * | params.market,
217 | * | cache.prices,
218 | * | true // shouldValidateMinCollateralUsd
219 | | );
220 | |
221 | * | if (!isLiquidatable) {
222 | | revert Errors.PositionShouldNotBeLiquidated(
223 | | reason,
224 | | info.remainingCollateralUsd,
225 | | info.minCollateralUsd,
226 | | info.minCollateralUsdForLeverage
227 | | );
228 | | }
229 | | }
230 | |
231 | * | cache.initialCollateralAmount = params.position.collateralAmount();
232 | * | (
233 | * | PositionUtils.DecreasePositionCollateralValues memory values,
234 | * | PositionPricingUtils.PositionFees memory fees
235 | * | ) = DecreasePositionCollateralUtils.processCollateral(
236 | * | params,
237 | * | cache
238 | | );
239 | |
240 | * | cache.nextPositionSizeInUsd = params.position.sizeInUsd() - params.order.sizeDeltaUsd();
241 | * | cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor(params.contracts.dataStore, params.market.marketToken, params.position.isLong());
242 | |
243 | * | PositionUtils.updateTotalBorrowing(
244 | * | params,
245 | * | cache.nextPositionSizeInUsd,
246 | * | cache.nextPositionBorrowingFactor
247 | | );
248 | |
249 | * | params.position.setSizeInUsd(cache.nextPositionSizeInUsd);
250 | * | params.position.setSizeInTokens(params.position.sizeInTokens() - values.sizeDeltaInTokens);
251 | * | params.position.setCollateralAmount(values.remainingCollateralAmount);
252 | * | params.position.setDecreasedAtBlock(Chain.currentBlockNumber());
253 | * | params.position.setDecreasedAtTime(Chain.currentTimestamp());
254 | |
255 | * | PositionUtils.incrementClaimableFundingAmount(params, fees);
256 | |
257 | * | if (params.position.sizeInUsd() == 0 || params.position.sizeInTokens() == 0) {
258 | | // withdraw all collateral if the position will be closed
259 | * | values.output.outputAmount += params.position.collateralAmount();
260 | |
261 | * | params.position.setSizeInUsd(0);
262 | * | params.position.setSizeInTokens(0);
263 | * | params.position.setCollateralAmount(0);
264 | |
265 | * | PositionStoreUtils.remove(params.contracts.dataStore, params.positionKey, params.order.account());
266 | | } else {
267 | * | params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor);
268 | |
269 | * | params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize);
270 | * | params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize);
271 | * | params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize);
272 | |
273 | * | PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position);
274 | | }
275 | |
276 | * | MarketUtils.applyDeltaToCollateralSum(
277 | * | params.contracts.dataStore,
278 | * | params.contracts.eventEmitter,
279 | * | params.position.market(),
280 | * | params.position.collateralToken(),
281 | * | params.position.isLong(),
282 | * | -(cache.initialCollateralAmount - params.position.collateralAmount()).toInt256()
283 | | );
284 | |
285 | * | PositionUtils.updateOpenInterest(
286 | * | params,
287 | * | -params.order.sizeDeltaUsd().toInt256(),
288 | * | -values.sizeDeltaInTokens.toInt256()
289 | | );
290 | |
291 | | // affiliate rewards are still distributed even if the order is a liquidation order
292 | | // this is expected as a partial liquidation is considered the same as an automatic
293 | | // closing of a position
294 | * | PositionUtils.handleReferral(params, fees);
295 | |
296 | | // validatePosition should be called after open interest and all other market variables
297 | | // have been updated
298 | * | if (params.position.sizeInUsd() != 0 || params.position.sizeInTokens() != 0) {
299 | | // validate position which validates liquidation state is only called
300 | | // if the remaining position size is not zero
301 | | // due to this, a user can still manually close their position if
302 | | // it is in a partially liquidatable state
303 | | // this should not cause any issues as a liquidation is the same
304 | | // as automatically closing a position
305 | | // the only difference is that if the position has insufficient / negative
306 | | // collateral a liquidation transaction should still complete
307 | | // while a manual close transaction should revert
308 | * | PositionUtils.validatePosition(
309 | * | params.contracts.dataStore,
310 | * | params.contracts.referralStorage,
311 | * | params.position,
312 | * | params.market,
313 | * | cache.prices,
314 | * | false, // shouldValidateMinPositionSize
315 | * | false // shouldValidateMinCollateralUsd
316 | | );
317 | | }
318 | |
319 | * | PositionEventUtils.emitPositionFeesCollected(
320 | * | params.contracts.eventEmitter,
321 | * | params.orderKey,
322 | * | params.positionKey,
323 | * | params.market.marketToken,
324 | * | params.position.collateralToken(),
325 | * | params.order.sizeDeltaUsd(),
326 | * | false,
327 | * | fees
328 | | );
329 | |
330 | * | PositionEventUtils.emitPositionDecrease(
331 | * | params.contracts.eventEmitter,
332 | * | params.orderKey,
333 | * | params.positionKey,
334 | * | params.position,
335 | * | params.order.sizeDeltaUsd(),
336 | * | cache.initialCollateralAmount - params.position.collateralAmount(),
337 | * | params.order.orderType(),
338 | * | values,
339 | * | cache.prices.indexTokenPrice,
340 | * | cache.collateralTokenPrice
341 | | );
342 | |
343 | * | values = DecreasePositionSwapUtils.swapWithdrawnCollateralToPnlToken(params, values);
344 | |
345 | * | return DecreasePositionResult(
346 | * | values.output.outputToken,
347 | * | values.output.outputAmount,
348 | * | values.output.secondaryOutputToken,
349 | * | values.output.secondaryOutputAmount,
350 | * | params.order.sizeDeltaUsd(),
351 | * | params.order.initialCollateralDeltaAmount()
352 | | );
353 | | }
354 | | }
355 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/IncreasePositionUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/Precision.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | | import "../event/EventEmitter.sol";
9 | |
10 | | import "../oracle/Oracle.sol";
11 | | import "../pricing/PositionPricingUtils.sol";
12 | |
13 | | import "./Position.sol";
14 | | import "./PositionStoreUtils.sol";
15 | | import "./PositionUtils.sol";
16 | | import "./PositionEventUtils.sol";
17 | | import "../order/BaseOrderUtils.sol";
18 | |
19 | | // @title IncreasePositionUtils
20 | | // @dev Library for functions to help with increasing a position
21 | * | library IncreasePositionUtils {
22 | | using SafeCast for uint256;
23 | | using SafeCast for int256;
24 | |
25 | | using Position for Position.Props;
26 | | using Order for Order.Props;
27 | | using Price for Price.Props;
28 | |
29 | | // @dev IncreasePositionCache struct used in increasePosition to
30 | | // avoid stack too deep errors
31 | | // @param collateralDeltaAmount the change in collateral amount
32 | | // @param executionPrice the execution price
33 | | // @param collateralTokenPrice the price of the collateral token
34 | | // @param priceImpactUsd the price impact in USD
35 | | // @param priceImpactAmount the price impact of the position increase in tokens
36 | | // @param sizeDeltaInTokens the change in position size in tokens
37 | | // @param nextPositionSizeInUsd the new position size in USD
38 | | // @param nextPositionBorrowingFactor the new position borrowing factor
39 | | struct IncreasePositionCache {
40 | | int256 collateralDeltaAmount;
41 | | uint256 executionPrice;
42 | | Price.Props collateralTokenPrice;
43 | | int256 priceImpactUsd;
44 | | int256 priceImpactAmount;
45 | | uint256 sizeDeltaInTokens;
46 | | uint256 nextPositionSizeInUsd;
47 | | uint256 nextPositionBorrowingFactor;
48 | | }
49 | |
50 | | // @dev increase a position
51 | | // The increasePosition function is used to increase the size of a position
52 | | // in a market. This involves updating the position's collateral amount,
53 | | // calculating the price impact of the size increase, and updating the position's
54 | | // size and borrowing factor. This function also applies fees to the position
55 | | // and updates the market's liquidity pool based on the new position size.
56 | | // @param params PositionUtils.UpdatePositionParams
57 | * | function increasePosition(
58 | | PositionUtils.UpdatePositionParams memory params,
59 | | uint256 collateralIncrementAmount
60 | * | ) internal {
61 | | // get the market prices for the given position
62 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(
63 | * | params.contracts.oracle,
64 | * | params.market
65 | | );
66 | |
67 | | // create a new cache for holding intermediate results
68 | * | IncreasePositionCache memory cache;
69 | |
70 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(
71 | * | params.position.collateralToken(),
72 | * | params.market,
73 | * | prices
74 | | );
75 | |
76 | * | if (params.position.sizeInUsd() == 0) {
77 | * | params.position.setFundingFeeAmountPerSize(
78 | * | MarketUtils.getFundingFeeAmountPerSize(
79 | * | params.contracts.dataStore,
80 | * | params.market.marketToken,
81 | * | params.position.collateralToken(),
82 | * | params.position.isLong()
83 | | )
84 | | );
85 | |
86 | * | params.position.setLongTokenClaimableFundingAmountPerSize(
87 | * | MarketUtils.getClaimableFundingAmountPerSize(
88 | * | params.contracts.dataStore,
89 | * | params.market.marketToken,
90 | * | params.market.longToken,
91 | * | params.position.isLong()
92 | | )
93 | | );
94 | |
95 | * | params.position.setShortTokenClaimableFundingAmountPerSize(
96 | * | MarketUtils.getClaimableFundingAmountPerSize(
97 | * | params.contracts.dataStore,
98 | * | params.market.marketToken,
99 | * | params.market.shortToken,
100 | * | params.position.isLong()
101 | | )
102 | | );
103 | | }
104 | |
105 | * | (cache.priceImpactUsd, cache.priceImpactAmount, cache.sizeDeltaInTokens, cache.executionPrice) = PositionUtils.getExecutionPriceForIncrease(params, prices.indexTokenPrice);
106 | |
107 | | // process the collateral for the given position and order
108 | * | PositionPricingUtils.PositionFees memory fees;
109 | * | (cache.collateralDeltaAmount, fees) = processCollateral(
110 | * | params,
111 | * | cache.collateralTokenPrice,
112 | * | collateralIncrementAmount.toInt256(),
113 | * | cache.priceImpactUsd
114 | | );
115 | |
116 | | // check if there is sufficient collateral for the position
117 | * | if (
118 | * | cache.collateralDeltaAmount < 0 &&
119 | * | params.position.collateralAmount() < SafeCast.toUint256(-cache.collateralDeltaAmount)
120 | | ) {
121 | | revert Errors.InsufficientCollateralAmount(params.position.collateralAmount(), cache.collateralDeltaAmount);
122 | | }
123 | * | params.position.setCollateralAmount(Calc.sumReturnUint256(params.position.collateralAmount(), cache.collateralDeltaAmount));
124 | |
125 | | // if there is a positive impact, the impact pool amount should be reduced
126 | | // if there is a negative impact, the impact pool amount should be increased
127 | * | MarketUtils.applyDeltaToPositionImpactPool(
128 | * | params.contracts.dataStore,
129 | * | params.contracts.eventEmitter,
130 | * | params.market.marketToken,
131 | * | -cache.priceImpactAmount
132 | | );
133 | |
134 | * | cache.nextPositionSizeInUsd = params.position.sizeInUsd() + params.order.sizeDeltaUsd();
135 | * | cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor(
136 | * | params.contracts.dataStore,
137 | * | params.market.marketToken,
138 | * | params.position.isLong()
139 | | );
140 | |
141 | * | PositionUtils.updateTotalBorrowing(
142 | * | params,
143 | * | cache.nextPositionSizeInUsd,
144 | * | cache.nextPositionBorrowingFactor
145 | | );
146 | |
147 | * | PositionUtils.incrementClaimableFundingAmount(params, fees);
148 | |
149 | * | params.position.setSizeInUsd(cache.nextPositionSizeInUsd);
150 | * | params.position.setSizeInTokens(params.position.sizeInTokens() + cache.sizeDeltaInTokens);
151 | |
152 | * | params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize);
153 | * | params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize);
154 | * | params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize);
155 | |
156 | * | params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor);
157 | * | params.position.setIncreasedAtBlock(Chain.currentBlockNumber());
158 | * | params.position.setIncreasedAtTime(Chain.currentTimestamp());
159 | |
160 | * | PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position);
161 | |
162 | * | PositionUtils.updateOpenInterest(
163 | * | params,
164 | * | params.order.sizeDeltaUsd().toInt256(),
165 | * | cache.sizeDeltaInTokens.toInt256()
166 | | );
167 | |
168 | * | if (params.order.sizeDeltaUsd() > 0) {
169 | | // reserves are only validated if the sizeDeltaUsd is more than zero
170 | | // this helps to ensure that deposits of collateral into positions
171 | | // should still succeed even if pool tokens are fully reserved
172 | * | MarketUtils.validateReserve(
173 | * | params.contracts.dataStore,
174 | * | params.market,
175 | * | prices,
176 | * | params.order.isLong()
177 | | );
178 | |
179 | * | MarketUtils.validateOpenInterestReserve(
180 | * | params.contracts.dataStore,
181 | * | params.market,
182 | * | prices,
183 | * | params.order.isLong()
184 | | );
185 | |
186 | * | PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues(
187 | * | params.position.sizeInUsd(), // positionSizeInUsd
188 | * | params.position.collateralAmount(), // positionCollateralAmount
189 | * | 0, // realizedPnlUsd
190 | * | 0 // openInterestDelta
191 | | );
192 | |
193 | * | (bool willBeSufficient, int256 remainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient(
194 | * | params.contracts.dataStore,
195 | * | params.market,
196 | * | prices,
197 | * | params.position.collateralToken(),
198 | * | params.position.isLong(),
199 | * | positionValues
200 | | );
201 | |
202 | * | if (!willBeSufficient) {
203 | * | revert Errors.InsufficientCollateralUsd(remainingCollateralUsd);
204 | | }
205 | | }
206 | |
207 | * | PositionUtils.handleReferral(params, fees);
208 | |
209 | | // validatePosition should be called after open interest and all other market variables
210 | | // have been updated
211 | * | PositionUtils.validatePosition(
212 | * | params.contracts.dataStore,
213 | * | params.contracts.referralStorage,
214 | * | params.position,
215 | * | params.market,
216 | * | prices,
217 | * | true, // shouldValidateMinPositionSize
218 | * | true // shouldValidateMinCollateralUsd
219 | | );
220 | |
221 | * | PositionEventUtils.emitPositionFeesCollected(
222 | * | params.contracts.eventEmitter,
223 | * | params.orderKey,
224 | * | params.positionKey,
225 | * | params.market.marketToken,
226 | * | params.position.collateralToken(),
227 | * | params.order.sizeDeltaUsd(),
228 | * | true,
229 | * | fees
230 | | );
231 | |
232 | * | PositionEventUtils.PositionIncreaseParams memory eventParams;
233 | * | eventParams.eventEmitter = params.contracts.eventEmitter;
234 | * | eventParams.orderKey = params.orderKey;
235 | * | eventParams.positionKey = params.positionKey;
236 | * | eventParams.position = params.position;
237 | * | eventParams.indexTokenPrice = prices.indexTokenPrice;
238 | * | eventParams.executionPrice = cache.executionPrice;
239 | * | eventParams.collateralTokenPrice = cache.collateralTokenPrice;
240 | * | eventParams.sizeDeltaUsd = params.order.sizeDeltaUsd();
241 | * | eventParams.sizeDeltaInTokens = cache.sizeDeltaInTokens;
242 | * | eventParams.collateralDeltaAmount = cache.collateralDeltaAmount;
243 | * | eventParams.priceImpactUsd = cache.priceImpactUsd;
244 | * | eventParams.priceImpactAmount = cache.priceImpactAmount;
245 | * | eventParams.orderType = params.order.orderType();
246 | |
247 | * | PositionEventUtils.emitPositionIncrease(eventParams);
248 | | }
249 | |
250 | | // @dev handle the collateral changes of the position
251 | | // @param params PositionUtils.UpdatePositionParams
252 | | // @param prices the prices of the tokens in the market
253 | | // @param position the position to process collateral for
254 | | // @param collateralDeltaAmount the change in the position's collateral
255 | * | function processCollateral(
256 | | PositionUtils.UpdatePositionParams memory params,
257 | | Price.Props memory collateralTokenPrice,
258 | | int256 collateralDeltaAmount,
259 | | int256 priceImpactUsd
260 | * | ) internal returns (int256, PositionPricingUtils.PositionFees memory) {
261 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(
262 | * | params.contracts.dataStore, // dataStore
263 | * | params.contracts.referralStorage, // referralStorage
264 | * | params.position, // position
265 | * | collateralTokenPrice, // collateralTokenPrice
266 | * | priceImpactUsd > 0, // forPositiveImpact
267 | * | params.market.longToken, // longToken
268 | * | params.market.shortToken, // shortToken
269 | * | params.order.sizeDeltaUsd(), // sizeDeltaUsd
270 | * | params.order.uiFeeReceiver() // uiFeeReceiver
271 | | );
272 | |
273 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);
274 | |
275 | * | FeeUtils.incrementClaimableFeeAmount(
276 | * | params.contracts.dataStore,
277 | * | params.contracts.eventEmitter,
278 | * | params.market.marketToken,
279 | * | params.position.collateralToken(),
280 | * | fees.feeReceiverAmount,
281 | | Keys.POSITION_FEE_TYPE
282 | | );
283 | |
284 | * | FeeUtils.incrementClaimableUiFeeAmount(
285 | * | params.contracts.dataStore,
286 | * | params.contracts.eventEmitter,
287 | * | params.order.uiFeeReceiver(),
288 | * | params.market.marketToken,
289 | * | params.position.collateralToken(),
290 | * | fees.ui.uiFeeAmount,
291 | | Keys.UI_POSITION_FEE_TYPE
292 | | );
293 | |
294 | * | collateralDeltaAmount -= fees.totalCostAmount.toInt256();
295 | |
296 | * | MarketUtils.applyDeltaToCollateralSum(
297 | * | params.contracts.dataStore,
298 | * | params.contracts.eventEmitter,
299 | * | params.order.market(),
300 | * | params.position.collateralToken(),
301 | * | params.order.isLong(),
302 | * | collateralDeltaAmount
303 | | );
304 | |
305 | * | MarketUtils.applyDeltaToPoolAmount(
306 | * | params.contracts.dataStore,
307 | * | params.contracts.eventEmitter,
308 | * | params.market,
309 | * | params.position.collateralToken(),
310 | * | fees.feeAmountForPool.toInt256()
311 | | );
312 | |
313 | * | return (collateralDeltaAmount, fees);
314 | | }
315 | | }
316 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/Position.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title Position
6 | | // @dev Stuct for positions
7 | | //
8 | | // borrowing fees for position require only a borrowingFactor to track
9 | | // an example on how this works is if the global cumulativeBorrowingFactor is 10020%
10 | | // a position would be opened with borrowingFactor as 10020%
11 | | // after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would
12 | | // owe 5% of the position size as borrowing fees
13 | | // the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs
14 | | // when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's
15 | | // collateral and transferred into the LP pool
16 | | //
17 | | // the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees
18 | | // based on the fiat value of the position sizes
19 | | //
20 | | // for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position
21 | | // claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would
22 | | // only owe 0.05 longToken ($200)
23 | | // this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts
24 | | // to be deducted and to be paid out need to be tracked instead
25 | | //
26 | | // for funding fees, there are four values to consider:
27 | | // 1. long positions with market.longToken as collateral
28 | | // 2. long positions with market.shortToken as collateral
29 | | // 3. short positions with market.longToken as collateral
30 | | // 4. short positions with market.shortToken as collateral
31 | * | library Position {
32 | | // @dev there is a limit on the number of fields a struct can have when being passed
33 | | // or returned as a memory variable which can cause "Stack too deep" errors
34 | | // use sub-structs to avoid this issue
35 | | // @param addresses address values
36 | | // @param numbers number values
37 | | // @param flags boolean values
38 | | struct Props {
39 | | Addresses addresses;
40 | | Numbers numbers;
41 | | Flags flags;
42 | | }
43 | |
44 | | // @param account the position's account
45 | | // @param market the position's market
46 | | // @param collateralToken the position's collateralToken
47 | | struct Addresses {
48 | | address account;
49 | | address market;
50 | | address collateralToken;
51 | | }
52 | |
53 | | // @param sizeInUsd the position's size in USD
54 | | // @param sizeInTokens the position's size in tokens
55 | | // @param collateralAmount the amount of collateralToken for collateral
56 | | // @param borrowingFactor the position's borrowing factor
57 | | // @param fundingFeeAmountPerSize the position's funding fee per size
58 | | // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size
59 | | // for the market.longToken
60 | | // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size
61 | | // for the market.shortToken
62 | | // @param increasedAtBlock the block at which the position was last increased
63 | | // @param decreasedAtBlock the block at which the position was last decreased
64 | | struct Numbers {
65 | | uint256 sizeInUsd;
66 | | uint256 sizeInTokens;
67 | | uint256 collateralAmount;
68 | | uint256 borrowingFactor;
69 | | uint256 fundingFeeAmountPerSize;
70 | | uint256 longTokenClaimableFundingAmountPerSize;
71 | | uint256 shortTokenClaimableFundingAmountPerSize;
72 | | uint256 increasedAtBlock;
73 | | uint256 decreasedAtBlock;
74 | | uint256 increasedAtTime;
75 | | uint256 decreasedAtTime;
76 | | }
77 | |
78 | | // @param isLong whether the position is a long or short
79 | | struct Flags {
80 | | bool isLong;
81 | | }
82 | |
83 | * | function account(Props memory props) internal pure returns (address) {
84 | * | return props.addresses.account;
85 | | }
86 | |
87 | * | function setAccount(Props memory props, address value) internal pure {
88 | * | props.addresses.account = value;
89 | | }
90 | |
91 | * | function market(Props memory props) internal pure returns (address) {
92 | * | return props.addresses.market;
93 | | }
94 | |
95 | * | function setMarket(Props memory props, address value) internal pure {
96 | * | props.addresses.market = value;
97 | | }
98 | |
99 | * | function collateralToken(Props memory props) internal pure returns (address) {
100 | * | return props.addresses.collateralToken;
101 | | }
102 | |
103 | * | function setCollateralToken(Props memory props, address value) internal pure {
104 | * | props.addresses.collateralToken = value;
105 | | }
106 | |
107 | * | function sizeInUsd(Props memory props) internal pure returns (uint256) {
108 | * | return props.numbers.sizeInUsd;
109 | | }
110 | |
111 | * | function setSizeInUsd(Props memory props, uint256 value) internal pure {
112 | * | props.numbers.sizeInUsd = value;
113 | | }
114 | |
115 | * | function sizeInTokens(Props memory props) internal pure returns (uint256) {
116 | * | return props.numbers.sizeInTokens;
117 | | }
118 | |
119 | * | function setSizeInTokens(Props memory props, uint256 value) internal pure {
120 | * | props.numbers.sizeInTokens = value;
121 | | }
122 | |
123 | * | function collateralAmount(Props memory props) internal pure returns (uint256) {
124 | * | return props.numbers.collateralAmount;
125 | | }
126 | |
127 | * | function setCollateralAmount(Props memory props, uint256 value) internal pure {
128 | * | props.numbers.collateralAmount = value;
129 | | }
130 | |
131 | * | function borrowingFactor(Props memory props) internal pure returns (uint256) {
132 | * | return props.numbers.borrowingFactor;
133 | | }
134 | |
135 | * | function setBorrowingFactor(Props memory props, uint256 value) internal pure {
136 | * | props.numbers.borrowingFactor = value;
137 | | }
138 | |
139 | * | function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {
140 | * | return props.numbers.fundingFeeAmountPerSize;
141 | | }
142 | |
143 | * | function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {
144 | * | props.numbers.fundingFeeAmountPerSize = value;
145 | | }
146 | |
147 | * | function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {
148 | * | return props.numbers.longTokenClaimableFundingAmountPerSize;
149 | | }
150 | |
151 | * | function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {
152 | * | props.numbers.longTokenClaimableFundingAmountPerSize = value;
153 | | }
154 | |
155 | * | function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {
156 | * | return props.numbers.shortTokenClaimableFundingAmountPerSize;
157 | | }
158 | |
159 | * | function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {
160 | * | props.numbers.shortTokenClaimableFundingAmountPerSize = value;
161 | | }
162 | |
163 | * | function increasedAtBlock(Props memory props) internal pure returns (uint256) {
164 | * | return props.numbers.increasedAtBlock;
165 | | }
166 | |
167 | * | function setIncreasedAtBlock(Props memory props, uint256 value) internal pure {
168 | * | props.numbers.increasedAtBlock = value;
169 | | }
170 | |
171 | * | function decreasedAtBlock(Props memory props) internal pure returns (uint256) {
172 | * | return props.numbers.decreasedAtBlock;
173 | | }
174 | |
175 | * | function setDecreasedAtBlock(Props memory props, uint256 value) internal pure {
176 | * | props.numbers.decreasedAtBlock = value;
177 | | }
178 | |
179 | * | function increasedAtTime(Props memory props) internal pure returns (uint256) {
180 | * | return props.numbers.increasedAtTime;
181 | | }
182 | |
183 | * | function setIncreasedAtTime(Props memory props, uint256 value) internal pure {
184 | * | props.numbers.increasedAtTime = value;
185 | | }
186 | |
187 | * | function decreasedAtTime(Props memory props) internal pure returns (uint256) {
188 | * | return props.numbers.decreasedAtTime;
189 | | }
190 | |
191 | * | function setDecreasedAtTime(Props memory props, uint256 value) internal pure {
192 | * | props.numbers.decreasedAtTime = value;
193 | | }
194 | |
195 | * | function isLong(Props memory props) internal pure returns (bool) {
196 | * | return props.flags.isLong;
197 | | }
198 | |
199 | * | function setIsLong(Props memory props, bool value) internal pure {
200 | * | props.flags.isLong = value;
201 | | }
202 | |
203 | | // @dev get the key for a position
204 | | // @param account the position's account
205 | | // @param market the position's market
206 | | // @param collateralToken the position's collateralToken
207 | | // @param isLong whether the position is long or short
208 | | // @return the position key
209 | * | function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {
210 | * | bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));
211 | * | return _key;
212 | | }
213 | | }
214 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./Position.sol";
10 | | import "./PositionUtils.sol";
11 | | import "../pricing/PositionPricingUtils.sol";
12 | |
13 | * | library PositionEventUtils {
14 | | using Position for Position.Props;
15 | |
16 | | using EventUtils for EventUtils.AddressItems;
17 | | using EventUtils for EventUtils.UintItems;
18 | | using EventUtils for EventUtils.IntItems;
19 | | using EventUtils for EventUtils.BoolItems;
20 | | using EventUtils for EventUtils.Bytes32Items;
21 | | using EventUtils for EventUtils.BytesItems;
22 | | using EventUtils for EventUtils.StringItems;
23 | |
24 | | struct PositionIncreaseParams {
25 | | EventEmitter eventEmitter;
26 | | bytes32 orderKey;
27 | | bytes32 positionKey;
28 | | Position.Props position;
29 | | Price.Props indexTokenPrice;
30 | | Price.Props collateralTokenPrice;
31 | | uint256 executionPrice;
32 | | uint256 sizeDeltaUsd;
33 | | uint256 sizeDeltaInTokens;
34 | | int256 collateralDeltaAmount;
35 | | int256 priceImpactUsd;
36 | | int256 priceImpactAmount;
37 | | Order.OrderType orderType;
38 | | }
39 | |
40 | * | function emitPositionIncrease(PositionIncreaseParams memory params) internal {
41 | * | EventUtils.EventLogData memory eventData;
42 | |
43 | * | eventData.addressItems.initItems(3);
44 | * | eventData.addressItems.setItem(0, "account", params.position.account());
45 | * | eventData.addressItems.setItem(1, "market", params.position.market());
46 | * | eventData.addressItems.setItem(2, "collateralToken", params.position.collateralToken());
47 | |
48 | * | eventData.uintItems.initItems(16);
49 | * | eventData.uintItems.setItem(0, "sizeInUsd", params.position.sizeInUsd());
50 | * | eventData.uintItems.setItem(1, "sizeInTokens", params.position.sizeInTokens());
51 | * | eventData.uintItems.setItem(2, "collateralAmount", params.position.collateralAmount());
52 | * | eventData.uintItems.setItem(3, "borrowingFactor", params.position.borrowingFactor());
53 | * | eventData.uintItems.setItem(4, "fundingFeeAmountPerSize", params.position.fundingFeeAmountPerSize());
54 | * | eventData.uintItems.setItem(5, "longTokenClaimableFundingAmountPerSize", params.position.longTokenClaimableFundingAmountPerSize());
55 | * | eventData.uintItems.setItem(6, "shortTokenClaimableFundingAmountPerSize", params.position.shortTokenClaimableFundingAmountPerSize());
56 | * | eventData.uintItems.setItem(7, "executionPrice", params.executionPrice);
57 | * | eventData.uintItems.setItem(8, "indexTokenPrice.max", params.indexTokenPrice.max);
58 | * | eventData.uintItems.setItem(9, "indexTokenPrice.min", params.indexTokenPrice.min);
59 | * | eventData.uintItems.setItem(10, "collateralTokenPrice.max", params.collateralTokenPrice.max);
60 | * | eventData.uintItems.setItem(11, "collateralTokenPrice.min", params.collateralTokenPrice.min);
61 | * | eventData.uintItems.setItem(12, "sizeDeltaUsd", params.sizeDeltaUsd);
62 | * | eventData.uintItems.setItem(13, "sizeDeltaInTokens", params.sizeDeltaInTokens);
63 | * | eventData.uintItems.setItem(14, "orderType", uint256(params.orderType));
64 | * | eventData.uintItems.setItem(15, "increasedAtTime", uint256(params.position.increasedAtTime()));
65 | |
66 | * | eventData.intItems.initItems(3);
67 | * | eventData.intItems.setItem(0, "collateralDeltaAmount", params.collateralDeltaAmount);
68 | * | eventData.intItems.setItem(1, "priceImpactUsd", params.priceImpactUsd);
69 | * | eventData.intItems.setItem(2, "priceImpactAmount", params.priceImpactAmount);
70 | |
71 | * | eventData.boolItems.initItems(1);
72 | * | eventData.boolItems.setItem(0, "isLong", params.position.isLong());
73 | |
74 | * | eventData.bytes32Items.initItems(2);
75 | * | eventData.bytes32Items.setItem(0, "orderKey", params.orderKey);
76 | * | eventData.bytes32Items.setItem(1, "positionKey", params.positionKey);
77 | |
78 | * | params.eventEmitter.emitEventLog1(
79 | | "PositionIncrease",
80 | * | Cast.toBytes32(params.position.account()),
81 | * | eventData
82 | | );
83 | | }
84 | |
85 | * | function emitPositionDecrease(
86 | | EventEmitter eventEmitter,
87 | | bytes32 orderKey,
88 | | bytes32 positionKey,
89 | | Position.Props memory position,
90 | | uint256 sizeDeltaUsd,
91 | | uint256 collateralDeltaAmount,
92 | | Order.OrderType orderType,
93 | | PositionUtils.DecreasePositionCollateralValues memory values,
94 | | Price.Props memory indexTokenPrice,
95 | | Price.Props memory collateralTokenPrice
96 | * | ) internal {
97 | * | EventUtils.EventLogData memory eventData;
98 | |
99 | * | eventData.addressItems.initItems(3);
100 | * | eventData.addressItems.setItem(0, "account", position.account());
101 | * | eventData.addressItems.setItem(1, "market", position.market());
102 | * | eventData.addressItems.setItem(2, "collateralToken", position.collateralToken());
103 | |
104 | * | eventData.uintItems.initItems(18);
105 | * | eventData.uintItems.setItem(0, "sizeInUsd", position.sizeInUsd());
106 | * | eventData.uintItems.setItem(1, "sizeInTokens", position.sizeInTokens());
107 | * | eventData.uintItems.setItem(2, "collateralAmount", position.collateralAmount());
108 | * | eventData.uintItems.setItem(3, "borrowingFactor", position.borrowingFactor());
109 | * | eventData.uintItems.setItem(4, "fundingFeeAmountPerSize", position.fundingFeeAmountPerSize());
110 | * | eventData.uintItems.setItem(5, "longTokenClaimableFundingAmountPerSize", position.longTokenClaimableFundingAmountPerSize());
111 | * | eventData.uintItems.setItem(6, "shortTokenClaimableFundingAmountPerSize", position.shortTokenClaimableFundingAmountPerSize());
112 | * | eventData.uintItems.setItem(7, "executionPrice", values.executionPrice);
113 | * | eventData.uintItems.setItem(8, "indexTokenPrice.max", indexTokenPrice.max);
114 | * | eventData.uintItems.setItem(9, "indexTokenPrice.min", indexTokenPrice.min);
115 | * | eventData.uintItems.setItem(10, "collateralTokenPrice.max", collateralTokenPrice.max);
116 | * | eventData.uintItems.setItem(11, "collateralTokenPrice.min", collateralTokenPrice.min);
117 | * | eventData.uintItems.setItem(12, "sizeDeltaUsd", sizeDeltaUsd);
118 | * | eventData.uintItems.setItem(13, "sizeDeltaInTokens", values.sizeDeltaInTokens);
119 | * | eventData.uintItems.setItem(14, "collateralDeltaAmount", collateralDeltaAmount);
120 | * | eventData.uintItems.setItem(15, "values.priceImpactDiffUsd", values.priceImpactDiffUsd);
121 | * | eventData.uintItems.setItem(16, "orderType", uint256(orderType));
122 | * | eventData.uintItems.setItem(17, "decreasedAtTime", position.decreasedAtTime());
123 | |
124 | * | eventData.intItems.initItems(3);
125 | * | eventData.intItems.setItem(0, "priceImpactUsd", values.priceImpactUsd);
126 | * | eventData.intItems.setItem(1, "basePnlUsd", values.basePnlUsd);
127 | * | eventData.intItems.setItem(2, "uncappedBasePnlUsd", values.uncappedBasePnlUsd);
128 | |
129 | * | eventData.boolItems.initItems(1);
130 | * | eventData.boolItems.setItem(0, "isLong", position.isLong());
131 | |
132 | * | eventData.bytes32Items.initItems(2);
133 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey);
134 | * | eventData.bytes32Items.setItem(1, "positionKey", positionKey);
135 | |
136 | * | eventEmitter.emitEventLog1(
137 | | "PositionDecrease",
138 | * | Cast.toBytes32(position.account()),
139 | * | eventData
140 | | );
141 | | }
142 | |
143 | * | function emitInsolventCloseInfo(
144 | | EventEmitter eventEmitter,
145 | | bytes32 orderKey,
146 | | uint256 positionCollateralAmount,
147 | | int256 basePnlUsd,
148 | | uint256 remainingCostUsd,
149 | | string memory step
150 | * | ) internal {
151 | * | EventUtils.EventLogData memory eventData;
152 | |
153 | * | eventData.bytes32Items.initItems(1);
154 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey);
155 | |
156 | * | eventData.uintItems.initItems(2);
157 | * | eventData.uintItems.setItem(0, "positionCollateralAmount", positionCollateralAmount);
158 | * | eventData.uintItems.setItem(1, "remainingCostUsd", remainingCostUsd);
159 | |
160 | * | eventData.intItems.initItems(1);
161 | * | eventData.intItems.setItem(0, "basePnlUsd", basePnlUsd);
162 | |
163 | * | eventData.stringItems.initItems(1);
164 | * | eventData.stringItems.setItem(0, "step", step);
165 | |
166 | * | eventEmitter.emitEventLog(
167 | | "InsolventClose",
168 | * | eventData
169 | | );
170 | | }
171 | |
172 | * | function emitInsufficientFundingFeePayment(
173 | | EventEmitter eventEmitter,
174 | | address market,
175 | | address token,
176 | | uint256 expectedAmount,
177 | | uint256 amountPaidInCollateralToken,
178 | | uint256 amountPaidInSecondaryOutputToken
179 | * | ) internal {
180 | * | EventUtils.EventLogData memory eventData;
181 | |
182 | * | eventData.addressItems.initItems(2);
183 | * | eventData.addressItems.setItem(0, "market", market);
184 | * | eventData.addressItems.setItem(1, "token", token);
185 | |
186 | * | eventData.uintItems.initItems(3);
187 | * | eventData.uintItems.setItem(0, "expectedAmount", expectedAmount);
188 | * | eventData.uintItems.setItem(1, "amountPaidInCollateralToken", amountPaidInCollateralToken);
189 | * | eventData.uintItems.setItem(2, "amountPaidInSecondaryOutputToken", amountPaidInSecondaryOutputToken);
190 | |
191 | * | eventEmitter.emitEventLog1(
192 | | "InsufficientFundingFeePayment",
193 | * | Cast.toBytes32(market),
194 | * | eventData
195 | | );
196 | | }
197 | |
198 | * | function emitPositionFeesCollected(
199 | | EventEmitter eventEmitter,
200 | | bytes32 orderKey,
201 | | bytes32 positionKey,
202 | | address market,
203 | | address collateralToken,
204 | | uint256 tradeSizeUsd,
205 | | bool isIncrease,
206 | | PositionPricingUtils.PositionFees memory fees
207 | | ) internal {
208 | * | _emitPositionFees(
209 | * | eventEmitter,
210 | * | orderKey,
211 | * | positionKey,
212 | * | market,
213 | * | collateralToken,
214 | * | tradeSizeUsd,
215 | * | isIncrease,
216 | * | fees,
217 | | "PositionFeesCollected"
218 | | );
219 | | }
220 | |
221 | * | function emitPositionFeesInfo(
222 | | EventEmitter eventEmitter,
223 | | bytes32 orderKey,
224 | | bytes32 positionKey,
225 | | address market,
226 | | address collateralToken,
227 | | uint256 tradeSizeUsd,
228 | | bool isIncrease,
229 | | PositionPricingUtils.PositionFees memory fees
230 | | ) internal {
231 | * | _emitPositionFees(
232 | * | eventEmitter,
233 | * | orderKey,
234 | * | positionKey,
235 | * | market,
236 | * | collateralToken,
237 | * | tradeSizeUsd,
238 | * | isIncrease,
239 | * | fees,
240 | | "PositionFeesInfo"
241 | | );
242 | | }
243 | |
244 | * | function _emitPositionFees(
245 | | EventEmitter eventEmitter,
246 | | bytes32 orderKey,
247 | | bytes32 positionKey,
248 | | address market,
249 | | address collateralToken,
250 | | uint256 tradeSizeUsd,
251 | | bool isIncrease,
252 | | PositionPricingUtils.PositionFees memory fees,
253 | | string memory eventName
254 | * | ) internal {
255 | * | EventUtils.EventLogData memory eventData;
256 | |
257 | * | eventData.bytes32Items.initItems(3);
258 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey);
259 | * | eventData.bytes32Items.setItem(1, "positionKey", positionKey);
260 | * | eventData.bytes32Items.setItem(2, "referralCode", fees.referral.referralCode);
261 | |
262 | * | eventData.addressItems.initItems(5);
263 | * | eventData.addressItems.setItem(0, "market", market);
264 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken);
265 | * | eventData.addressItems.setItem(2, "affiliate", fees.referral.affiliate);
266 | * | eventData.addressItems.setItem(3, "trader", fees.referral.trader);
267 | * | eventData.addressItems.setItem(4, "uiFeeReceiver", fees.ui.uiFeeReceiver);
268 | |
269 | | // in case the position was insolvent, the fundingFeeAmount and feeAmountForPool
270 | | // values may not be accurate
271 | * | eventData.uintItems.initItems(28);
272 | * | eventData.uintItems.setItem(0, "collateralTokenPrice.min", fees.collateralTokenPrice.min);
273 | * | eventData.uintItems.setItem(1, "collateralTokenPrice.max", fees.collateralTokenPrice.max);
274 | * | eventData.uintItems.setItem(2, "tradeSizeUsd", tradeSizeUsd);
275 | * | eventData.uintItems.setItem(3, "totalRebateFactor", fees.referral.totalRebateFactor);
276 | * | eventData.uintItems.setItem(4, "traderDiscountFactor", fees.referral.traderDiscountFactor);
277 | * | eventData.uintItems.setItem(5, "totalRebateAmount", fees.referral.totalRebateAmount);
278 | * | eventData.uintItems.setItem(6, "traderDiscountAmount", fees.referral.traderDiscountAmount);
279 | * | eventData.uintItems.setItem(7, "affiliateRewardAmount", fees.referral.affiliateRewardAmount);
280 | * | eventData.uintItems.setItem(8, "fundingFeeAmount", fees.funding.fundingFeeAmount);
281 | * | eventData.uintItems.setItem(9, "claimableLongTokenAmount", fees.funding.claimableLongTokenAmount);
282 | * | eventData.uintItems.setItem(10, "claimableShortTokenAmount", fees.funding.claimableShortTokenAmount);
283 | * | eventData.uintItems.setItem(11, "latestFundingFeeAmountPerSize", fees.funding.latestFundingFeeAmountPerSize);
284 | * | eventData.uintItems.setItem(12, "latestLongTokenClaimableFundingAmountPerSize", fees.funding.latestLongTokenClaimableFundingAmountPerSize);
285 | * | eventData.uintItems.setItem(13, "latestShortTokenClaimableFundingAmountPerSize", fees.funding.latestShortTokenClaimableFundingAmountPerSize);
286 | * | eventData.uintItems.setItem(14, "borrowingFeeUsd", fees.borrowing.borrowingFeeUsd);
287 | * | eventData.uintItems.setItem(15, "borrowingFeeAmount", fees.borrowing.borrowingFeeAmount);
288 | * | eventData.uintItems.setItem(16, "borrowingFeeReceiverFactor", fees.borrowing.borrowingFeeReceiverFactor);
289 | * | eventData.uintItems.setItem(17, "borrowingFeeAmountForFeeReceiver", fees.borrowing.borrowingFeeAmountForFeeReceiver);
290 | * | eventData.uintItems.setItem(18, "positionFeeFactor", fees.positionFeeFactor);
291 | * | eventData.uintItems.setItem(19, "protocolFeeAmount", fees.protocolFeeAmount);
292 | * | eventData.uintItems.setItem(20, "positionFeeReceiverFactor", fees.positionFeeReceiverFactor);
293 | * | eventData.uintItems.setItem(21, "feeReceiverAmount", fees.feeReceiverAmount);
294 | * | eventData.uintItems.setItem(22, "feeAmountForPool", fees.feeAmountForPool);
295 | * | eventData.uintItems.setItem(23, "positionFeeAmountForPool", fees.positionFeeAmountForPool);
296 | * | eventData.uintItems.setItem(24, "positionFeeAmount", fees.positionFeeAmount);
297 | * | eventData.uintItems.setItem(25, "totalCostAmount", fees.totalCostAmount);
298 | * | eventData.uintItems.setItem(26, "uiFeeReceiverFactor", fees.ui.uiFeeReceiverFactor);
299 | * | eventData.uintItems.setItem(27, "uiFeeAmount", fees.ui.uiFeeAmount);
300 | |
301 | * | eventData.boolItems.initItems(1);
302 | * | eventData.boolItems.setItem(0, "isIncrease", isIncrease);
303 | |
304 | * | eventEmitter.emitEventLog1(
305 | * | eventName,
306 | * | Cast.toBytes32(market),
307 | * | eventData
308 | | );
309 | | }
310 | | }
311 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Position.sol";
9 | |
10 | | /**
11 | | * @title PositionStoreUtils
12 | | * @dev Library for position storage functions
13 | | */
14 | * | library PositionStoreUtils {
15 | | using Position for Position.Props;
16 | |
17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
18 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET"));
19 | * | bytes32 internal constant COLLATERAL_TOKEN = keccak256(abi.encode("COLLATERAL_TOKEN"));
20 | |
21 | * | bytes32 internal constant SIZE_IN_USD = keccak256(abi.encode("SIZE_IN_USD"));
22 | * | bytes32 internal constant SIZE_IN_TOKENS = keccak256(abi.encode("SIZE_IN_TOKENS"));
23 | * | bytes32 internal constant COLLATERAL_AMOUNT = keccak256(abi.encode("COLLATERAL_AMOUNT"));
24 | * | bytes32 internal constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR"));
25 | * | bytes32 internal constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE"));
26 | * | bytes32 internal constant LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
27 | * | bytes32 internal constant SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
28 | * | bytes32 internal constant INCREASED_AT_BLOCK = keccak256(abi.encode("INCREASED_AT_BLOCK"));
29 | * | bytes32 internal constant DECREASED_AT_BLOCK = keccak256(abi.encode("DECREASED_AT_BLOCK"));
30 | * | bytes32 internal constant INCREASED_AT_TIME = keccak256(abi.encode("INCREASED_AT_TIME"));
31 | * | bytes32 internal constant DECREASED_AT_TIME = keccak256(abi.encode("DECREASED_AT_TIME"));
32 | |
33 | * | bytes32 internal constant IS_LONG = keccak256(abi.encode("IS_LONG"));
34 | |
35 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Position.Props memory) {
36 | * | Position.Props memory position;
37 | * | if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {
38 | * | return position;
39 | | }
40 | |
41 | * | position.setAccount(dataStore.getAddress(
42 | * | keccak256(abi.encode(key, ACCOUNT))
43 | | ));
44 | |
45 | * | position.setMarket(dataStore.getAddress(
46 | * | keccak256(abi.encode(key, MARKET))
47 | | ));
48 | |
49 | * | position.setCollateralToken(dataStore.getAddress(
50 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN))
51 | | ));
52 | |
53 | * | position.setSizeInUsd(dataStore.getUint(
54 | * | keccak256(abi.encode(key, SIZE_IN_USD))
55 | | ));
56 | |
57 | * | position.setSizeInTokens(dataStore.getUint(
58 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS))
59 | | ));
60 | |
61 | * | position.setCollateralAmount(dataStore.getUint(
62 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT))
63 | | ));
64 | |
65 | * | position.setBorrowingFactor(dataStore.getUint(
66 | * | keccak256(abi.encode(key, BORROWING_FACTOR))
67 | | ));
68 | |
69 | * | position.setFundingFeeAmountPerSize(dataStore.getUint(
70 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))
71 | | ));
72 | |
73 | * | position.setLongTokenClaimableFundingAmountPerSize(dataStore.getUint(
74 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
75 | | ));
76 | |
77 | * | position.setShortTokenClaimableFundingAmountPerSize(dataStore.getUint(
78 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
79 | | ));
80 | |
81 | * | position.setIncreasedAtBlock(dataStore.getUint(
82 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK))
83 | | ));
84 | |
85 | * | position.setDecreasedAtBlock(dataStore.getUint(
86 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK))
87 | | ));
88 | |
89 | * | position.setIncreasedAtTime(dataStore.getUint(
90 | * | keccak256(abi.encode(key, INCREASED_AT_TIME))
91 | | ));
92 | |
93 | * | position.setDecreasedAtTime(dataStore.getUint(
94 | * | keccak256(abi.encode(key, DECREASED_AT_TIME))
95 | | ));
96 | |
97 | * | position.setIsLong(dataStore.getBool(
98 | * | keccak256(abi.encode(key, IS_LONG))
99 | | ));
100 | |
101 | * | return position;
102 | | }
103 | |
104 | * | function set(DataStore dataStore, bytes32 key, Position.Props memory position) internal {
105 | * | dataStore.addBytes32(
106 | | Keys.POSITION_LIST,
107 | * | key
108 | | );
109 | |
110 | * | dataStore.addBytes32(
111 | * | Keys.accountPositionListKey(position.account()),
112 | * | key
113 | | );
114 | |
115 | * | dataStore.setAddress(
116 | * | keccak256(abi.encode(key, ACCOUNT)),
117 | * | position.account()
118 | | );
119 | |
120 | * | dataStore.setAddress(
121 | * | keccak256(abi.encode(key, MARKET)),
122 | * | position.market()
123 | | );
124 | |
125 | * | dataStore.setAddress(
126 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN)),
127 | * | position.collateralToken()
128 | | );
129 | |
130 | * | dataStore.setUint(
131 | * | keccak256(abi.encode(key, SIZE_IN_USD)),
132 | * | position.sizeInUsd()
133 | | );
134 | |
135 | * | dataStore.setUint(
136 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS)),
137 | * | position.sizeInTokens()
138 | | );
139 | |
140 | * | dataStore.setUint(
141 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT)),
142 | * | position.collateralAmount()
143 | | );
144 | |
145 | * | dataStore.setUint(
146 | * | keccak256(abi.encode(key, BORROWING_FACTOR)),
147 | * | position.borrowingFactor()
148 | | );
149 | |
150 | * | dataStore.setUint(
151 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)),
152 | * | position.fundingFeeAmountPerSize()
153 | | );
154 | |
155 | * | dataStore.setUint(
156 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),
157 | * | position.longTokenClaimableFundingAmountPerSize()
158 | | );
159 | |
160 | * | dataStore.setUint(
161 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),
162 | * | position.shortTokenClaimableFundingAmountPerSize()
163 | | );
164 | |
165 | * | dataStore.setUint(
166 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK)),
167 | * | position.increasedAtBlock()
168 | | );
169 | |
170 | * | dataStore.setUint(
171 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK)),
172 | * | position.decreasedAtBlock()
173 | | );
174 | |
175 | * | dataStore.setUint(
176 | * | keccak256(abi.encode(key, INCREASED_AT_TIME)),
177 | * | position.increasedAtTime()
178 | | );
179 | |
180 | * | dataStore.setUint(
181 | * | keccak256(abi.encode(key, DECREASED_AT_TIME)),
182 | * | position.decreasedAtTime()
183 | | );
184 | |
185 | * | dataStore.setBool(
186 | * | keccak256(abi.encode(key, IS_LONG)),
187 | * | position.isLong()
188 | | );
189 | | }
190 | |
191 | * | function remove(DataStore dataStore, bytes32 key, address account) internal {
192 | * | if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {
193 | | revert Errors.PositionNotFound(key);
194 | | }
195 | |
196 | * | dataStore.removeBytes32(
197 | | Keys.POSITION_LIST,
198 | * | key
199 | | );
200 | |
201 | * | dataStore.removeBytes32(
202 | * | Keys.accountPositionListKey(account),
203 | * | key
204 | | );
205 | |
206 | * | dataStore.removeAddress(
207 | * | keccak256(abi.encode(key, ACCOUNT))
208 | | );
209 | |
210 | * | dataStore.removeAddress(
211 | * | keccak256(abi.encode(key, MARKET))
212 | | );
213 | |
214 | * | dataStore.removeAddress(
215 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN))
216 | | );
217 | |
218 | * | dataStore.removeUint(
219 | * | keccak256(abi.encode(key, SIZE_IN_USD))
220 | | );
221 | |
222 | * | dataStore.removeUint(
223 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS))
224 | | );
225 | |
226 | * | dataStore.removeUint(
227 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT))
228 | | );
229 | |
230 | * | dataStore.removeUint(
231 | * | keccak256(abi.encode(key, BORROWING_FACTOR))
232 | | );
233 | |
234 | * | dataStore.removeUint(
235 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))
236 | | );
237 | |
238 | * | dataStore.removeUint(
239 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
240 | | );
241 | |
242 | * | dataStore.removeUint(
243 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
244 | | );
245 | |
246 | * | dataStore.removeUint(
247 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK))
248 | | );
249 | |
250 | * | dataStore.removeUint(
251 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK))
252 | | );
253 | |
254 | * | dataStore.removeUint(
255 | * | keccak256(abi.encode(key, INCREASED_AT_TIME))
256 | | );
257 | |
258 | * | dataStore.removeUint(
259 | * | keccak256(abi.encode(key, DECREASED_AT_TIME))
260 | | );
261 | |
262 | * | dataStore.removeBool(
263 | * | keccak256(abi.encode(key, IS_LONG))
264 | | );
265 | | }
266 | |
267 | * | function getPositionCount(DataStore dataStore) internal view returns (uint256) {
268 | * | return dataStore.getBytes32Count(Keys.POSITION_LIST);
269 | | }
270 | |
271 | | function getPositionKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
272 | | return dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end);
273 | | }
274 | |
275 | | function getAccountPositionCount(DataStore dataStore, address account) internal view returns (uint256) {
276 | | return dataStore.getBytes32Count(Keys.accountPositionListKey(account));
277 | | }
278 | |
279 | * | function getAccountPositionKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
280 | * | return dataStore.getBytes32ValuesAt(Keys.accountPositionListKey(account), start, end);
281 | | }
282 | | }
283 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
6 | |
7 | | import "../utils/Precision.sol";
8 | |
9 | | import "./Position.sol";
10 | |
11 | | import "../data/DataStore.sol";
12 | | import "../data/Keys.sol";
13 | |
14 | | import "../pricing/PositionPricingUtils.sol";
15 | | import "../order/BaseOrderUtils.sol";
16 | |
17 | | // @title PositionUtils
18 | | // @dev Library for position functions
19 | * | library PositionUtils {
20 | | using SafeCast for uint256;
21 | | using SafeCast for int256;
22 | | using Price for Price.Props;
23 | | using Position for Position.Props;
24 | | using Order for Order.Props;
25 | |
26 | | // @dev UpdatePositionParams struct used in increasePosition and decreasePosition
27 | | // to avoid stack too deep errors
28 | | //
29 | | // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts
30 | | // @param market the values of the trading market
31 | | // @param order the decrease position order
32 | | // @param orderKey the key of the order
33 | | // @param position the order's position
34 | | // @param positionKey the key of the order's position
35 | | struct UpdatePositionParams {
36 | | BaseOrderUtils.ExecuteOrderParamsContracts contracts;
37 | | Market.Props market;
38 | | Order.Props order;
39 | | bytes32 orderKey;
40 | | Position.Props position;
41 | | bytes32 positionKey;
42 | | Order.SecondaryOrderType secondaryOrderType;
43 | | }
44 | |
45 | | // @param dataStore DataStore
46 | | // @param eventEmitter EventEmitter
47 | | // @param oracle Oracle
48 | | // @param referralStorage IReferralStorage
49 | | struct UpdatePositionParamsContracts {
50 | | DataStore dataStore;
51 | | EventEmitter eventEmitter;
52 | | Oracle oracle;
53 | | SwapHandler swapHandler;
54 | | IReferralStorage referralStorage;
55 | | }
56 | |
57 | | struct WillPositionCollateralBeSufficientValues {
58 | | uint256 positionSizeInUsd;
59 | | uint256 positionCollateralAmount;
60 | | int256 realizedPnlUsd;
61 | | int256 openInterestDelta;
62 | | }
63 | |
64 | | struct DecreasePositionCollateralValuesOutput {
65 | | address outputToken;
66 | | uint256 outputAmount;
67 | | address secondaryOutputToken;
68 | | uint256 secondaryOutputAmount;
69 | | }
70 | |
71 | | // @dev ProcessCollateralValues struct used to contain the values in processCollateral
72 | | // @param executionPrice the order execution price
73 | | // @param remainingCollateralAmount the remaining collateral amount of the position
74 | | // @param positionPnlUsd the pnl of the position in USD
75 | | // @param sizeDeltaInTokens the change in position size in tokens
76 | | // @param priceImpactAmount the price impact in tokens
77 | | // @param priceImpactDiffUsd the price impact difference in USD
78 | | // @param pendingCollateralDeduction the pending collateral deduction
79 | | // @param output DecreasePositionCollateralValuesOutput
80 | | struct DecreasePositionCollateralValues {
81 | | uint256 executionPrice;
82 | | uint256 remainingCollateralAmount;
83 | | int256 basePnlUsd;
84 | | int256 uncappedBasePnlUsd;
85 | | uint256 sizeDeltaInTokens;
86 | | int256 priceImpactUsd;
87 | | uint256 priceImpactDiffUsd;
88 | | DecreasePositionCollateralValuesOutput output;
89 | | }
90 | |
91 | | // @dev DecreasePositionCache struct used in decreasePosition to
92 | | // avoid stack too deep errors
93 | | // @param prices the prices of the tokens in the market
94 | | // @param pnlToken the token that the pnl for the user is in, for long positions
95 | | // this is the market.longToken, for short positions this is the market.shortToken
96 | | // @param pnlTokenPrice the price of the pnlToken
97 | | // @param initialCollateralAmount the initial collateral amount
98 | | // @param nextPositionSizeInUsd the new position size in USD
99 | | // @param nextPositionBorrowingFactor the new position borrowing factor
100 | | struct DecreasePositionCache {
101 | | MarketUtils.MarketPrices prices;
102 | | int256 estimatedPositionPnlUsd;
103 | | int256 estimatedRealizedPnlUsd;
104 | | int256 estimatedRemainingPnlUsd;
105 | | address pnlToken;
106 | | Price.Props pnlTokenPrice;
107 | | Price.Props collateralTokenPrice;
108 | | uint256 initialCollateralAmount;
109 | | uint256 nextPositionSizeInUsd;
110 | | uint256 nextPositionBorrowingFactor;
111 | | }
112 | |
113 | |
114 | | struct GetPositionPnlUsdCache {
115 | | int256 positionValue;
116 | | int256 totalPositionPnl;
117 | | int256 uncappedTotalPositionPnl;
118 | | address pnlToken;
119 | | uint256 poolTokenAmount;
120 | | uint256 poolTokenPrice;
121 | | uint256 poolTokenUsd;
122 | | int256 poolPnl;
123 | | int256 cappedPoolPnl;
124 | | uint256 sizeDeltaInTokens;
125 | | int256 positionPnlUsd;
126 | | int256 uncappedPositionPnlUsd;
127 | | }
128 | |
129 | | struct IsPositionLiquidatableInfo {
130 | | int256 remainingCollateralUsd;
131 | | int256 minCollateralUsd;
132 | | int256 minCollateralUsdForLeverage;
133 | | }
134 | |
135 | | // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable
136 | | // to avoid stack too deep errors
137 | | // @param positionPnlUsd the position's pnl in USD
138 | | // @param minCollateralFactor the min collateral factor
139 | | // @param collateralTokenPrice the collateral token price
140 | | // @param collateralUsd the position's collateral in USD
141 | | // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation
142 | | // @param priceImpactUsd the price impact of closing the position in USD
143 | | struct IsPositionLiquidatableCache {
144 | | int256 positionPnlUsd;
145 | | uint256 minCollateralFactor;
146 | | Price.Props collateralTokenPrice;
147 | | uint256 collateralUsd;
148 | | int256 usdDeltaForPriceImpact;
149 | | int256 priceImpactUsd;
150 | | bool hasPositiveImpact;
151 | | }
152 | |
153 | | struct GetExecutionPriceForDecreaseCache {
154 | | int256 priceImpactUsd;
155 | | uint256 priceImpactDiffUsd;
156 | | uint256 executionPrice;
157 | | }
158 | |
159 | | // @dev get the position pnl in USD
160 | | //
161 | | // for long positions, pnl is calculated as:
162 | | // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd
163 | | // if position.sizeInTokens is larger for long positions, the position will have
164 | | // larger profits and smaller losses for the same changes in token price
165 | | //
166 | | // for short positions, pnl is calculated as:
167 | | // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice)
168 | | // if position.sizeInTokens is smaller for long positions, the position will have
169 | | // larger profits and smaller losses for the same changes in token price
170 | | //
171 | | // @param position the position values
172 | | // @param sizeDeltaUsd the change in position size
173 | | // @param indexTokenPrice the price of the index token
174 | | //
175 | | // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens)
176 | * | function getPositionPnlUsd(
177 | | DataStore dataStore,
178 | | Market.Props memory market,
179 | | MarketUtils.MarketPrices memory prices,
180 | | Position.Props memory position,
181 | | uint256 sizeDeltaUsd
182 | * | ) internal view returns (int256, int256, uint256) {
183 | * | GetPositionPnlUsdCache memory cache;
184 | |
185 | * | uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);
186 | |
187 | | // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens
188 | * | cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();
189 | * | cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;
190 | * | cache.uncappedTotalPositionPnl = cache.totalPositionPnl;
191 | |
192 | * | if (cache.totalPositionPnl > 0) {
193 | * | cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;
194 | * | cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);
195 | * | cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;
196 | * | cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;
197 | * | cache.poolPnl = MarketUtils.getPnl(
198 | * | dataStore,
199 | * | market,
200 | * | prices.indexTokenPrice,
201 | * | position.isLong(),
202 | * | true
203 | | );
204 | |
205 | * | cache.cappedPoolPnl = MarketUtils.getCappedPnl(
206 | * | dataStore,
207 | * | market.marketToken,
208 | * | position.isLong(),
209 | * | cache.poolPnl,
210 | * | cache.poolTokenUsd,
211 | | Keys.MAX_PNL_FACTOR_FOR_TRADERS
212 | | );
213 | |
214 | * | if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {
215 | | cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());
216 | | }
217 | | }
218 | |
219 | * | if (position.sizeInUsd() == sizeDeltaUsd) {
220 | * | cache.sizeDeltaInTokens = position.sizeInTokens();
221 | | } else {
222 | * | if (position.isLong()) {
223 | * | cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());
224 | | } else {
225 | | cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();
226 | | }
227 | | }
228 | |
229 | * | cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());
230 | * | cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());
231 | |
232 | * | return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);
233 | | }
234 | |
235 | | // @dev validate that a position is not empty
236 | | // @param position the position values
237 | * | function validateNonEmptyPosition(Position.Props memory position) internal pure {
238 | * | if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {
239 | * | revert Errors.EmptyPosition();
240 | | }
241 | | }
242 | |
243 | | // @dev check if a position is valid
244 | | // @param dataStore DataStore
245 | | // @param referralStorage IReferralStorage
246 | | // @param position the position values
247 | | // @param market the market values
248 | | // @param prices the prices of the tokens in the market
249 | | // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated
250 | | // validation is skipped for decrease position to prevent reverts in case the order size
251 | | // is just slightly smaller than the position size
252 | | // in decrease position, the remaining collateral is estimated at the start, and the order
253 | | // size is updated to match the position size if the remaining collateral will be less than
254 | | // the min collateral usd
255 | | // since this is an estimate, there may be edge cases where there is a small remaining position size
256 | | // and small amount of collateral remaining
257 | | // validation is skipped for this case as it is preferred for the order to be executed
258 | | // since the small amount of collateral remaining only impacts the potential payment of liquidation
259 | | // keepers
260 | * | function validatePosition(
261 | | DataStore dataStore,
262 | | IReferralStorage referralStorage,
263 | | Position.Props memory position,
264 | | Market.Props memory market,
265 | | MarketUtils.MarketPrices memory prices,
266 | | bool shouldValidateMinPositionSize,
267 | | bool shouldValidateMinCollateralUsd
268 | * | ) internal view {
269 | * | if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {
270 | * | revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());
271 | | }
272 | |
273 | * | MarketUtils.validateEnabledMarket(dataStore, market.marketToken);
274 | * | MarketUtils.validateMarketCollateralToken(market, position.collateralToken());
275 | |
276 | * | if (shouldValidateMinPositionSize) {
277 | * | uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);
278 | * | if (position.sizeInUsd() < minPositionSizeUsd) {
279 | * | revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);
280 | | }
281 | | }
282 | |
283 | * | (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(
284 | * | dataStore,
285 | * | referralStorage,
286 | * | position,
287 | * | market,
288 | * | prices,
289 | * | shouldValidateMinCollateralUsd
290 | | );
291 | |
292 | * | if (isLiquidatable) {
293 | * | revert Errors.LiquidatablePosition(
294 | * | reason,
295 | * | info.remainingCollateralUsd,
296 | * | info.minCollateralUsd,
297 | * | info.minCollateralUsdForLeverage
298 | | );
299 | | }
300 | | }
301 | |
302 | | // @dev check if a position is liquidatable
303 | | // @param dataStore DataStore
304 | | // @param referralStorage IReferralStorage
305 | | // @param position the position values
306 | | // @param market the market values
307 | | // @param prices the prices of the tokens in the market
308 | * | function isPositionLiquidatable(
309 | | DataStore dataStore,
310 | | IReferralStorage referralStorage,
311 | | Position.Props memory position,
312 | | Market.Props memory market,
313 | | MarketUtils.MarketPrices memory prices,
314 | | bool shouldValidateMinCollateralUsd
315 | * | ) internal view returns (bool, string memory, IsPositionLiquidatableInfo memory) {
316 | * | IsPositionLiquidatableCache memory cache;
317 | * | IsPositionLiquidatableInfo memory info;
318 | |
319 | * | (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd(
320 | * | dataStore,
321 | * | market,
322 | * | prices,
323 | * | position,
324 | * | position.sizeInUsd()
325 | | );
326 | |
327 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(
328 | * | position.collateralToken(),
329 | * | market,
330 | * | prices
331 | | );
332 | |
333 | * | cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;
334 | |
335 | | // calculate the usdDeltaForPriceImpact for fully closing the position
336 | * | cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();
337 | |
338 | * | cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
339 | * | PositionPricingUtils.GetPriceImpactUsdParams(
340 | * | dataStore,
341 | * | market,
342 | * | cache.usdDeltaForPriceImpact,
343 | * | position.isLong()
344 | | )
345 | | );
346 | |
347 | * | cache.hasPositiveImpact = cache.priceImpactUsd > 0;
348 | |
349 | | // even if there is a large positive price impact, positions that would be liquidated
350 | | // if the positive price impact is reduced should not be allowed to be created
351 | | // as they would be easily liquidated if the price impact changes
352 | | // cap the priceImpactUsd to zero to prevent these positions from being created
353 | * | if (cache.priceImpactUsd >= 0) {
354 | * | cache.priceImpactUsd = 0;
355 | | } else {
356 | | uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(
357 | | dataStore,
358 | | market.marketToken
359 | | );
360 | |
361 | | // if there is a large build up of open interest and a sudden large price movement
362 | | // it may result in a large imbalance between longs and shorts
363 | | // this could result in very large price impact temporarily
364 | | // cap the max negative price impact to prevent cascading liquidations
365 | | int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();
366 | | if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {
367 | | cache.priceImpactUsd = maxNegativePriceImpactUsd;
368 | | }
369 | | }
370 | |
371 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(
372 | * | dataStore, // dataStore
373 | * | referralStorage, // referralStorage
374 | * | position, // position
375 | * | cache.collateralTokenPrice, //collateralTokenPrice
376 | * | cache.hasPositiveImpact, // forPositiveImpact
377 | * | market.longToken, // longToken
378 | * | market.shortToken, // shortToken
379 | * | position.sizeInUsd(), // sizeDeltaUsd
380 | * | address(0) // uiFeeReceiver
381 | | );
382 | |
383 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);
384 | |
385 | | // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD
386 | | // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated
387 | | // using collateralTokenPrice.min
388 | * | uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;
389 | |
390 | | // the position's pnl is counted as collateral for the liquidation check
391 | | // as a position in profit should not be liquidated if the pnl is sufficient
392 | | // to cover the position's fees
393 | * | info.remainingCollateralUsd =
394 | * | cache.collateralUsd.toInt256()
395 | * | + cache.positionPnlUsd
396 | * | + cache.priceImpactUsd
397 | * | - collateralCostUsd.toInt256();
398 | |
399 | * | cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);
400 | |
401 | | // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded)
402 | | // this validation includes the position fee to be paid when closing the position
403 | | // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position
404 | * | info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();
405 | |
406 | * | if (shouldValidateMinCollateralUsd) {
407 | * | info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();
408 | * | if (info.remainingCollateralUsd < info.minCollateralUsd) {
409 | * | return (true, "min collateral", info);
410 | | }
411 | | }
412 | |
413 | * | if (info.remainingCollateralUsd <= 0) {
414 | | return (true, "< 0", info);
415 | | }
416 | |
417 | * | if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {
418 | * | return (true, "min collateral for leverage", info);
419 | | }
420 | |
421 | * | return (false, "", info);
422 | | }
423 | |
424 | | // fees and price impact are not included for the willPositionCollateralBeSufficient validation
425 | | // this is because this validation is meant to guard against a specific scenario of price impact
426 | | // gaming
427 | | //
428 | | // price impact could be gamed by opening high leverage positions, if the price impact
429 | | // that should be charged is higher than the amount of collateral in the position
430 | | // then a user could pay less price impact than what is required, and there is a risk that
431 | | // price manipulation could be profitable if the price impact cost is less than it should be
432 | | //
433 | | // this check should be sufficient even without factoring in fees as fees should have a minimal impact
434 | | // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could
435 | | // lead to a user paying less price impact than they should, however gaming of this form should be difficult
436 | | // since the funding and borrowing fees would still add up for the user's cost
437 | | //
438 | | // another possibility would be if a user opens a large amount of both long and short positions, and
439 | | // funding fees are paid from one side to the other, but since most of the open interest is owned by the
440 | | // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant
441 | | // since some time would be required for the funding fees to accumulate
442 | | //
443 | | // fees and price impact are validated in the validatePosition check
444 | * | function willPositionCollateralBeSufficient(
445 | | DataStore dataStore,
446 | | Market.Props memory market,
447 | | MarketUtils.MarketPrices memory prices,
448 | | address collateralToken,
449 | | bool isLong,
450 | | WillPositionCollateralBeSufficientValues memory values
451 | * | ) internal view returns (bool, int256) {
452 | * | Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(
453 | * | collateralToken,
454 | * | market,
455 | * | prices
456 | | );
457 | |
458 | * | int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();
459 | |
460 | | // deduct realized pnl if it is negative since this would be paid from
461 | | // the position's collateral
462 | * | if (values.realizedPnlUsd < 0) {
463 | * | remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;
464 | | }
465 | |
466 | * | if (remainingCollateralUsd < 0) {
467 | * | return (false, remainingCollateralUsd);
468 | | }
469 | |
470 | | // the min collateral factor will increase as the open interest for a market increases
471 | | // this may lead to previously created limit increase orders not being executable
472 | | //
473 | | // the position's pnl is not factored into the remainingCollateralUsd value, since
474 | | // factoring in a positive pnl may allow the user to manipulate price and bypass this check
475 | | // it may be useful to factor in a negative pnl for this check, this can be added if required
476 | * | uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(
477 | * | dataStore,
478 | * | market,
479 | * | values.openInterestDelta,
480 | * | isLong
481 | | );
482 | |
483 | * | uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);
484 | | // use the minCollateralFactor for the market if it is larger
485 | * | if (minCollateralFactorForMarket > minCollateralFactor) {
486 | * | minCollateralFactor = minCollateralFactorForMarket;
487 | | }
488 | |
489 | * | int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();
490 | * | bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;
491 | |
492 | * | return (willBeSufficient, remainingCollateralUsd);
493 | | }
494 | |
495 | * | function updateFundingAndBorrowingState(
496 | | DataStore dataStore,
497 | | EventEmitter eventEmitter,
498 | | Market.Props memory market,
499 | | MarketUtils.MarketPrices memory prices
500 | | ) internal {
501 | | // update the funding amount per size for the market
502 | * | MarketUtils.updateFundingState(
503 | * | dataStore,
504 | * | eventEmitter,
505 | * | market,
506 | * | prices
507 | | );
508 | |
509 | | // update the cumulative borrowing factor for longs
510 | * | MarketUtils.updateCumulativeBorrowingFactor(
511 | * | dataStore,
512 | * | eventEmitter,
513 | * | market,
514 | * | prices,
515 | * | true // isLong
516 | | );
517 | |
518 | | // update the cumulative borrowing factor for shorts
519 | * | MarketUtils.updateCumulativeBorrowingFactor(
520 | * | dataStore,
521 | * | eventEmitter,
522 | * | market,
523 | * | prices,
524 | * | false // isLong
525 | | );
526 | | }
527 | |
528 | * | function updateTotalBorrowing(
529 | | PositionUtils.UpdatePositionParams memory params,
530 | | uint256 nextPositionSizeInUsd,
531 | | uint256 nextPositionBorrowingFactor
532 | | ) internal {
533 | * | MarketUtils.updateTotalBorrowing(
534 | * | params.contracts.dataStore, // dataStore
535 | * | params.market.marketToken, // market
536 | * | params.position.isLong(), // isLong
537 | * | params.position.sizeInUsd(), // prevPositionSizeInUsd
538 | * | params.position.borrowingFactor(), // prevPositionBorrowingFactor
539 | * | nextPositionSizeInUsd, // nextPositionSizeInUsd
540 | * | nextPositionBorrowingFactor // nextPositionBorrowingFactor
541 | | );
542 | | }
543 | |
544 | | // the order.receiver is meant to allow the output of an order to be
545 | | // received by an address that is different from the position.account
546 | | // address
547 | | // for funding fees, the funds are still credited to the owner
548 | | // of the position indicated by order.account
549 | * | function incrementClaimableFundingAmount(
550 | | PositionUtils.UpdatePositionParams memory params,
551 | | PositionPricingUtils.PositionFees memory fees
552 | | ) internal {
553 | | // if the position has negative funding fees, distribute it to allow it to be claimable
554 | * | if (fees.funding.claimableLongTokenAmount > 0) {
555 | * | MarketUtils.incrementClaimableFundingAmount(
556 | * | params.contracts.dataStore,
557 | * | params.contracts.eventEmitter,
558 | * | params.market.marketToken,
559 | * | params.market.longToken,
560 | * | params.order.account(),
561 | * | fees.funding.claimableLongTokenAmount
562 | | );
563 | | }
564 | |
565 | * | if (fees.funding.claimableShortTokenAmount > 0) {
566 | * | MarketUtils.incrementClaimableFundingAmount(
567 | * | params.contracts.dataStore,
568 | * | params.contracts.eventEmitter,
569 | * | params.market.marketToken,
570 | * | params.market.shortToken,
571 | * | params.order.account(),
572 | * | fees.funding.claimableShortTokenAmount
573 | | );
574 | | }
575 | | }
576 | |
577 | * | function updateOpenInterest(
578 | | PositionUtils.UpdatePositionParams memory params,
579 | | int256 sizeDeltaUsd,
580 | | int256 sizeDeltaInTokens
581 | | ) internal {
582 | * | if (sizeDeltaUsd != 0) {
583 | * | MarketUtils.applyDeltaToOpenInterest(
584 | * | params.contracts.dataStore,
585 | * | params.contracts.eventEmitter,
586 | * | params.market,
587 | * | params.position.collateralToken(),
588 | * | params.position.isLong(),
589 | * | sizeDeltaUsd
590 | | );
591 | |
592 | * | MarketUtils.applyDeltaToOpenInterestInTokens(
593 | * | params.contracts.dataStore,
594 | * | params.contracts.eventEmitter,
595 | * | params.position.market(),
596 | * | params.position.collateralToken(),
597 | * | params.position.isLong(),
598 | * | sizeDeltaInTokens
599 | | );
600 | | }
601 | | }
602 | |
603 | * | function handleReferral(
604 | | PositionUtils.UpdatePositionParams memory params,
605 | | PositionPricingUtils.PositionFees memory fees
606 | | ) internal {
607 | * | ReferralUtils.incrementAffiliateReward(
608 | * | params.contracts.dataStore,
609 | * | params.contracts.eventEmitter,
610 | * | params.position.market(),
611 | * | params.position.collateralToken(),
612 | * | fees.referral.affiliate,
613 | * | fees.referral.affiliateRewardAmount
614 | | );
615 | | }
616 | |
617 | | // returns priceImpactUsd, priceImpactAmount, sizeDeltaInTokens, executionPrice
618 | * | function getExecutionPriceForIncrease(
619 | | UpdatePositionParams memory params,
620 | | Price.Props memory indexTokenPrice
621 | * | ) internal view returns (int256, int256, uint256, uint256) {
622 | | // note that the executionPrice is not validated against the order.acceptablePrice value
623 | | // if the sizeDeltaUsd is zero
624 | | // for limit orders the order.triggerPrice should still have been validated
625 | * | if (params.order.sizeDeltaUsd() == 0) {
626 | | // increase order:
627 | | // - long: use the larger price
628 | | // - short: use the smaller price
629 | * | return (0, 0, 0, indexTokenPrice.pickPrice(params.position.isLong()));
630 | | }
631 | |
632 | * | int256 priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
633 | * | PositionPricingUtils.GetPriceImpactUsdParams(
634 | * | params.contracts.dataStore,
635 | * | params.market,
636 | * | params.order.sizeDeltaUsd().toInt256(),
637 | * | params.order.isLong()
638 | | )
639 | | );
640 | |
641 | | // cap priceImpactUsd based on the amount available in the position impact pool
642 | * | priceImpactUsd = MarketUtils.getCappedPositionImpactUsd(
643 | * | params.contracts.dataStore,
644 | * | params.market.marketToken,
645 | * | indexTokenPrice,
646 | * | priceImpactUsd,
647 | * | params.order.sizeDeltaUsd()
648 | | );
649 | |
650 | | // for long positions
651 | | //
652 | | // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount
653 | | // the priceImpactAmount should be minimized
654 | | //
655 | | // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount
656 | | // the priceImpactAmount should be maximized
657 | |
658 | | // for short positions
659 | | //
660 | | // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount
661 | | // the priceImpactAmount should be minimized
662 | | //
663 | | // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount
664 | | // the priceImpactAmount should be maximized
665 | |
666 | * | int256 priceImpactAmount;
667 | |
668 | * | if (priceImpactUsd > 0) {
669 | | // use indexTokenPrice.max and round down to minimize the priceImpactAmount
670 | | priceImpactAmount = priceImpactUsd / indexTokenPrice.max.toInt256();
671 | | } else {
672 | | // use indexTokenPrice.min and round up to maximize the priceImpactAmount
673 | * | priceImpactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, indexTokenPrice.min);
674 | | }
675 | |
676 | * | uint256 baseSizeDeltaInTokens;
677 | |
678 | * | if (params.position.isLong()) {
679 | | // round the number of tokens for long positions down
680 | * | baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / indexTokenPrice.max;
681 | | } else {
682 | | // round the number of tokens for short positions up
683 | * | baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), indexTokenPrice.min);
684 | | }
685 | |
686 | * | int256 sizeDeltaInTokens;
687 | * | if (params.position.isLong()) {
688 | * | sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() + priceImpactAmount;
689 | | } else {
690 | * | sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() - priceImpactAmount;
691 | | }
692 | |
693 | * | if (sizeDeltaInTokens < 0) {
694 | | revert Errors.PriceImpactLargerThanOrderSize(priceImpactUsd, params.order.sizeDeltaUsd());
695 | | }
696 | |
697 | | // using increase of long positions as an example
698 | | // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000
699 | | // priceImpactAmount = -1000 / 2000 = -0.5
700 | | // baseSizeDeltaInTokens = 5000 / 2000 = 2.5
701 | | // sizeDeltaInTokens = 2.5 - 0.5 = 2
702 | | // executionPrice = 5000 / 2 = $2500
703 | * | uint256 executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(
704 | * | params.order.sizeDeltaUsd(),
705 | * | sizeDeltaInTokens.toUint256(),
706 | * | params.order.acceptablePrice(),
707 | * | params.position.isLong()
708 | | );
709 | |
710 | * | return (priceImpactUsd, priceImpactAmount, sizeDeltaInTokens.toUint256(), executionPrice);
711 | | }
712 | |
713 | | // returns priceImpactUsd, priceImpactDiffUsd, executionPrice
714 | * | function getExecutionPriceForDecrease(
715 | | UpdatePositionParams memory params,
716 | | Price.Props memory indexTokenPrice
717 | * | ) internal view returns (int256, uint256, uint256) {
718 | * | uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();
719 | |
720 | | // note that the executionPrice is not validated against the order.acceptablePrice value
721 | | // if the sizeDeltaUsd is zero
722 | | // for limit orders the order.triggerPrice should still have been validated
723 | * | if (sizeDeltaUsd == 0) {
724 | | // decrease order:
725 | | // - long: use the smaller price
726 | | // - short: use the larger price
727 | * | return (0, 0, indexTokenPrice.pickPrice(!params.position.isLong()));
728 | | }
729 | |
730 | * | GetExecutionPriceForDecreaseCache memory cache;
731 | |
732 | * | cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
733 | * | PositionPricingUtils.GetPriceImpactUsdParams(
734 | * | params.contracts.dataStore,
735 | * | params.market,
736 | * | -sizeDeltaUsd.toInt256(),
737 | * | params.order.isLong()
738 | | )
739 | | );
740 | |
741 | | // cap priceImpactUsd based on the amount available in the position impact pool
742 | * | cache.priceImpactUsd = MarketUtils.getCappedPositionImpactUsd(
743 | * | params.contracts.dataStore,
744 | * | params.market.marketToken,
745 | * | indexTokenPrice,
746 | * | cache.priceImpactUsd,
747 | * | sizeDeltaUsd
748 | | );
749 | |
750 | * | if (cache.priceImpactUsd < 0) {
751 | | uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactor(
752 | | params.contracts.dataStore,
753 | | params.market.marketToken,
754 | | false
755 | | );
756 | |
757 | | // convert the max price impact to the min negative value
758 | | // e.g. if sizeDeltaUsd is 10,000 and maxPriceImpactFactor is 2%
759 | | // then minPriceImpactUsd = -200
760 | | int256 minPriceImpactUsd = -Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();
761 | |
762 | | // cap priceImpactUsd to the min negative value and store the difference in priceImpactDiffUsd
763 | | // e.g. if priceImpactUsd is -500 and minPriceImpactUsd is -200
764 | | // then set priceImpactDiffUsd to -200 - -500 = 300
765 | | // set priceImpactUsd to -200
766 | | if (cache.priceImpactUsd < minPriceImpactUsd) {
767 | | cache.priceImpactDiffUsd = (minPriceImpactUsd - cache.priceImpactUsd).toUint256();
768 | | cache.priceImpactUsd = minPriceImpactUsd;
769 | | }
770 | | }
771 | |
772 | | // the executionPrice is calculated after the price impact is capped
773 | | // so the output amount directly received by the user may not match
774 | | // the executionPrice, the difference would be stored as a
775 | | // claimable amount
776 | * | cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(
777 | * | indexTokenPrice,
778 | * | params.position.sizeInUsd(),
779 | * | params.position.sizeInTokens(),
780 | * | sizeDeltaUsd,
781 | * | cache.priceImpactUsd,
782 | * | params.order.acceptablePrice(),
783 | * | params.position.isLong()
784 | | );
785 | |
786 | * | return (cache.priceImpactUsd, cache.priceImpactDiffUsd, cache.executionPrice);
787 | | }
788 | |
789 | | }
790 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/price/Price.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title Price
6 | | // @dev Struct for prices
7 | * | library Price {
8 | | // @param min the min price
9 | | // @param max the max price
10 | | struct Props {
11 | | uint256 min;
12 | | uint256 max;
13 | | }
14 | |
15 | | // @dev check if a price is empty
16 | | // @param props Props
17 | | // @return whether a price is empty
18 | * | function isEmpty(Props memory props) internal pure returns (bool) {
19 | * | return props.min == 0 || props.max == 0;
20 | | }
21 | |
22 | | // @dev get the average of the min and max values
23 | | // @param props Props
24 | | // @return the average of the min and max values
25 | * | function midPrice(Props memory props) internal pure returns (uint256) {
26 | * | return (props.max + props.min) / 2;
27 | | }
28 | |
29 | | // @dev pick either the min or max value
30 | | // @param props Props
31 | | // @param maximize whether to pick the min or max value
32 | | // @return either the min or max value
33 | * | function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {
34 | * | return maximize ? props.max : props.min;
35 | | }
36 | |
37 | | // @dev pick the min or max price depending on whether it is for a long or short position
38 | | // and whether the pending pnl should be maximized or not
39 | | // @param props Props
40 | | // @param isLong whether it is for a long or short position
41 | | // @param maximize whether the pnl should be maximized or not
42 | | // @return the min or max price
43 | * | function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {
44 | | // for long positions, pick the larger price to maximize pnl
45 | | // for short positions, pick the smaller price to maximize pnl
46 | * | if (isLong) {
47 | * | return maximize ? props.max : props.min;
48 | | }
49 | |
50 | * | return maximize ? props.min : props.max;
51 | | }
52 | | }
53 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/ISwapPricingUtils.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | interface ISwapPricingUtils {
6 | | enum SwapPricingType {
7 | | TwoStep,
8 | | Shift,
9 | | Atomic
10 | | }
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/PositionPricingUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../market/MarketUtils.sol";
8 | |
9 | | import "../utils/Precision.sol";
10 | | import "../utils/Calc.sol";
11 | |
12 | | import "./PricingUtils.sol";
13 | |
14 | | import "../referral/IReferralStorage.sol";
15 | | import "../referral/ReferralUtils.sol";
16 | |
17 | | // @title PositionPricingUtils
18 | | // @dev Library for position pricing functions
19 | * | library PositionPricingUtils {
20 | | using SignedMath for int256;
21 | | using SafeCast for uint256;
22 | | using SafeCast for int256;
23 | | using Position for Position.Props;
24 | | using Price for Price.Props;
25 | |
26 | | using EventUtils for EventUtils.AddressItems;
27 | | using EventUtils for EventUtils.UintItems;
28 | | using EventUtils for EventUtils.IntItems;
29 | | using EventUtils for EventUtils.BoolItems;
30 | | using EventUtils for EventUtils.Bytes32Items;
31 | | using EventUtils for EventUtils.BytesItems;
32 | | using EventUtils for EventUtils.StringItems;
33 | |
34 | | struct GetPositionFeesParams {
35 | | DataStore dataStore;
36 | | IReferralStorage referralStorage;
37 | | Position.Props position;
38 | | Price.Props collateralTokenPrice;
39 | | bool forPositiveImpact;
40 | | address longToken;
41 | | address shortToken;
42 | | uint256 sizeDeltaUsd;
43 | | address uiFeeReceiver;
44 | | }
45 | |
46 | | // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack
47 | | // too deep errors
48 | | // @param dataStore DataStore
49 | | // @param market the market to check
50 | | // @param usdDelta the change in position size in USD
51 | | // @param isLong whether the position is long or short
52 | | struct GetPriceImpactUsdParams {
53 | | DataStore dataStore;
54 | | Market.Props market;
55 | | int256 usdDelta;
56 | | bool isLong;
57 | | }
58 | |
59 | | // @dev OpenInterestParams struct to contain open interest values
60 | | // @param longOpenInterest the amount of long open interest
61 | | // @param shortOpenInterest the amount of short open interest
62 | | // @param nextLongOpenInterest the updated amount of long open interest
63 | | // @param nextShortOpenInterest the updated amount of short open interest
64 | | struct OpenInterestParams {
65 | | uint256 longOpenInterest;
66 | | uint256 shortOpenInterest;
67 | | uint256 nextLongOpenInterest;
68 | | uint256 nextShortOpenInterest;
69 | | }
70 | |
71 | | // @dev PositionFees struct to contain fee values
72 | | // @param feeReceiverAmount the amount for the fee receiver
73 | | // @param feeAmountForPool the amount of fees for the pool
74 | | // @param positionFeeAmountForPool the position fee amount for the pool
75 | | // @param positionFeeAmount the fee amount for increasing / decreasing the position
76 | | // @param borrowingFeeAmount the borrowing fee amount
77 | | // @param totalCostAmount the total cost amount in tokens
78 | | struct PositionFees {
79 | | PositionReferralFees referral;
80 | | PositionFundingFees funding;
81 | | PositionBorrowingFees borrowing;
82 | | PositionUiFees ui;
83 | | Price.Props collateralTokenPrice;
84 | | uint256 positionFeeFactor;
85 | | uint256 protocolFeeAmount;
86 | | uint256 positionFeeReceiverFactor;
87 | | uint256 feeReceiverAmount;
88 | | uint256 feeAmountForPool;
89 | | uint256 positionFeeAmountForPool;
90 | | uint256 positionFeeAmount;
91 | | uint256 totalCostAmountExcludingFunding;
92 | | uint256 totalCostAmount;
93 | | }
94 | |
95 | | // @param affiliate the referral affiliate of the trader
96 | | // @param traderDiscountAmount the discount amount for the trader
97 | | // @param affiliateRewardAmount the affiliate reward amount
98 | | struct PositionReferralFees {
99 | | bytes32 referralCode;
100 | | address affiliate;
101 | | address trader;
102 | | uint256 totalRebateFactor;
103 | | uint256 traderDiscountFactor;
104 | | uint256 totalRebateAmount;
105 | | uint256 traderDiscountAmount;
106 | | uint256 affiliateRewardAmount;
107 | | }
108 | |
109 | | struct PositionBorrowingFees {
110 | | uint256 borrowingFeeUsd;
111 | | uint256 borrowingFeeAmount;
112 | | uint256 borrowingFeeReceiverFactor;
113 | | uint256 borrowingFeeAmountForFeeReceiver;
114 | | }
115 | |
116 | | // @param fundingFeeAmount the position's funding fee amount
117 | | // @param claimableLongTokenAmount the negative funding fee in long token that is claimable
118 | | // @param claimableShortTokenAmount the negative funding fee in short token that is claimable
119 | | // @param latestLongTokenFundingAmountPerSize the latest long token funding
120 | | // amount per size for the market
121 | | // @param latestShortTokenFundingAmountPerSize the latest short token funding
122 | | // amount per size for the market
123 | | struct PositionFundingFees {
124 | | uint256 fundingFeeAmount;
125 | | uint256 claimableLongTokenAmount;
126 | | uint256 claimableShortTokenAmount;
127 | | uint256 latestFundingFeeAmountPerSize;
128 | | uint256 latestLongTokenClaimableFundingAmountPerSize;
129 | | uint256 latestShortTokenClaimableFundingAmountPerSize;
130 | | }
131 | |
132 | | struct PositionUiFees {
133 | | address uiFeeReceiver;
134 | | uint256 uiFeeReceiverFactor;
135 | | uint256 uiFeeAmount;
136 | | }
137 | |
138 | | // @dev get the price impact in USD for a position increase / decrease
139 | | // @param params GetPriceImpactUsdParams
140 | * | function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) {
141 | * | OpenInterestParams memory openInterestParams = getNextOpenInterest(params);
142 | |
143 | * | int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);
144 | |
145 | | // the virtual price impact calculation is skipped if the price impact
146 | | // is positive since the action is helping to balance the pool
147 | | //
148 | | // in case two virtual pools are unbalanced in a different direction
149 | | // e.g. pool0 has more longs than shorts while pool1 has less longs
150 | | // than shorts
151 | | // not skipping the virtual price impact calculation would lead to
152 | | // a negative price impact for any trade on either pools and would
153 | | // disincentivise the balancing of pools
154 | * | if (priceImpactUsd >= 0) { return priceImpactUsd; }
155 | |
156 | * | (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);
157 | * | if (!hasVirtualInventory) { return priceImpactUsd; }
158 | |
159 | | OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);
160 | | int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);
161 | |
162 | | return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd;
163 | | }
164 | |
165 | | // @dev get the price impact in USD for a position increase / decrease
166 | | // @param dataStore DataStore
167 | | // @param market the trading market
168 | | // @param openInterestParams OpenInterestParams
169 | * | function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256) {
170 | * | uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);
171 | * | uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);
172 | |
173 | | // check whether an improvement in balance comes from causing the balance to switch sides
174 | | // for example, if there is $2000 of ETH and $1000 of USDC in the pool
175 | | // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not
176 | | // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case
177 | * | bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;
178 | * | uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));
179 | |
180 | * | if (isSameSideRebalance) {
181 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
182 | * | uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, hasPositiveImpact);
183 | |
184 | * | return PricingUtils.getPriceImpactUsdForSameSideRebalance(
185 | * | initialDiffUsd,
186 | * | nextDiffUsd,
187 | * | impactFactor,
188 | * | impactExponentFactor
189 | | );
190 | | } else {
191 | * | (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);
192 | |
193 | * | return PricingUtils.getPriceImpactUsdForCrossoverRebalance(
194 | * | initialDiffUsd,
195 | * | nextDiffUsd,
196 | * | positiveImpactFactor,
197 | * | negativeImpactFactor,
198 | * | impactExponentFactor
199 | | );
200 | | }
201 | | }
202 | |
203 | | // @dev get the next open interest values
204 | | // @param params GetPriceImpactUsdParams
205 | | // @return OpenInterestParams
206 | * | function getNextOpenInterest(
207 | | GetPriceImpactUsdParams memory params
208 | * | ) internal view returns (OpenInterestParams memory) {
209 | * | uint256 longOpenInterest = MarketUtils.getOpenInterest(
210 | * | params.dataStore,
211 | * | params.market,
212 | * | true
213 | | );
214 | |
215 | * | uint256 shortOpenInterest = MarketUtils.getOpenInterest(
216 | * | params.dataStore,
217 | * | params.market,
218 | * | false
219 | | );
220 | |
221 | * | return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);
222 | | }
223 | |
224 | | function getNextOpenInterestForVirtualInventory(
225 | | GetPriceImpactUsdParams memory params,
226 | | int256 virtualInventory
227 | | ) internal pure returns (OpenInterestParams memory) {
228 | | uint256 longOpenInterest;
229 | | uint256 shortOpenInterest;
230 | |
231 | | // if virtualInventory is more than zero it means that
232 | | // tokens were virtually sold to the pool, so set shortOpenInterest
233 | | // to the virtualInventory value
234 | | // if virtualInventory is less than zero it means that
235 | | // tokens were virtually bought from the pool, so set longOpenInterest
236 | | // to the virtualInventory value
237 | | if (virtualInventory > 0) {
238 | | shortOpenInterest = virtualInventory.toUint256();
239 | | } else {
240 | | longOpenInterest = (-virtualInventory).toUint256();
241 | | }
242 | |
243 | | // the virtual long and short open interest is adjusted by the usdDelta
244 | | // to prevent an underflow in getNextOpenInterestParams
245 | | // price impact depends on the change in USD balance, so offsetting both
246 | | // values equally should not change the price impact calculation
247 | | if (params.usdDelta < 0) {
248 | | uint256 offset = (-params.usdDelta).toUint256();
249 | | longOpenInterest += offset;
250 | | shortOpenInterest += offset;
251 | | }
252 | |
253 | | return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);
254 | | }
255 | |
256 | * | function getNextOpenInterestParams(
257 | | GetPriceImpactUsdParams memory params,
258 | | uint256 longOpenInterest,
259 | | uint256 shortOpenInterest
260 | * | ) internal pure returns (OpenInterestParams memory) {
261 | * | uint256 nextLongOpenInterest = longOpenInterest;
262 | * | uint256 nextShortOpenInterest = shortOpenInterest;
263 | |
264 | * | if (params.isLong) {
265 | * | if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {
266 | | revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);
267 | | }
268 | |
269 | * | nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);
270 | | } else {
271 | * | if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {
272 | | revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);
273 | | }
274 | |
275 | * | nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);
276 | | }
277 | |
278 | * | OpenInterestParams memory openInterestParams = OpenInterestParams(
279 | * | longOpenInterest,
280 | * | shortOpenInterest,
281 | * | nextLongOpenInterest,
282 | * | nextShortOpenInterest
283 | | );
284 | |
285 | * | return openInterestParams;
286 | | }
287 | |
288 | | // @dev get position fees
289 | | // @param dataStore DataStore
290 | | // @param referralStorage IReferralStorage
291 | | // @param position the position values
292 | | // @param collateralTokenPrice the price of the position's collateralToken
293 | | // @param longToken the long token of the market
294 | | // @param shortToken the short token of the market
295 | | // @param sizeDeltaUsd the change in position size
296 | | // @return PositionFees
297 | * | function getPositionFees(
298 | | GetPositionFeesParams memory params
299 | * | ) internal view returns (PositionFees memory) {
300 | * | PositionFees memory fees = getPositionFeesAfterReferral(
301 | * | params.dataStore,
302 | * | params.referralStorage,
303 | * | params.collateralTokenPrice,
304 | * | params.forPositiveImpact,
305 | * | params.position.account(),
306 | * | params.position.market(),
307 | * | params.sizeDeltaUsd
308 | | );
309 | |
310 | * | uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);
311 | |
312 | * | fees.borrowing = getBorrowingFees(
313 | * | params.dataStore,
314 | * | params.collateralTokenPrice,
315 | * | borrowingFeeUsd
316 | | );
317 | |
318 | * | fees.feeAmountForPool = fees.positionFeeAmountForPool + fees.borrowing.borrowingFeeAmount - fees.borrowing.borrowingFeeAmountForFeeReceiver;
319 | * | fees.feeReceiverAmount += fees.borrowing.borrowingFeeAmountForFeeReceiver;
320 | |
321 | * | fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(
322 | * | params.dataStore,
323 | * | params.position.market(),
324 | * | params.position.collateralToken(),
325 | * | params.position.isLong()
326 | | );
327 | |
328 | * | fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
329 | * | params.dataStore,
330 | * | params.position.market(),
331 | * | params.longToken,
332 | * | params.position.isLong()
333 | | );
334 | |
335 | * | fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
336 | * | params.dataStore,
337 | * | params.position.market(),
338 | * | params.shortToken,
339 | * | params.position.isLong()
340 | | );
341 | |
342 | * | fees.funding = getFundingFees(
343 | * | fees.funding,
344 | * | params.position
345 | | );
346 | |
347 | * | fees.ui = getUiFees(
348 | * | params.dataStore,
349 | * | params.collateralTokenPrice,
350 | * | params.sizeDeltaUsd,
351 | * | params.uiFeeReceiver
352 | | );
353 | |
354 | * | fees.totalCostAmountExcludingFunding =
355 | * | fees.positionFeeAmount
356 | * | + fees.borrowing.borrowingFeeAmount
357 | * | + fees.ui.uiFeeAmount
358 | * | - fees.referral.traderDiscountAmount;
359 | |
360 | * | fees.totalCostAmount =
361 | * | fees.totalCostAmountExcludingFunding
362 | * | + fees.funding.fundingFeeAmount;
363 | |
364 | * | return fees;
365 | | }
366 | |
367 | * | function getBorrowingFees(
368 | | DataStore dataStore,
369 | | Price.Props memory collateralTokenPrice,
370 | | uint256 borrowingFeeUsd
371 | * | ) internal view returns (PositionBorrowingFees memory) {
372 | * | PositionBorrowingFees memory borrowingFees;
373 | |
374 | * | borrowingFees.borrowingFeeUsd = borrowingFeeUsd;
375 | * | borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;
376 | * | borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);
377 | * | borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);
378 | |
379 | * | return borrowingFees;
380 | | }
381 | |
382 | * | function getFundingFees(
383 | | PositionFundingFees memory fundingFees,
384 | | Position.Props memory position
385 | * | ) internal pure returns (PositionFundingFees memory) {
386 | * | fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(
387 | * | fundingFees.latestFundingFeeAmountPerSize,
388 | * | position.fundingFeeAmountPerSize(),
389 | * | position.sizeInUsd(),
390 | * | true // roundUpMagnitude
391 | | );
392 | |
393 | * | fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(
394 | * | fundingFees.latestLongTokenClaimableFundingAmountPerSize,
395 | * | position.longTokenClaimableFundingAmountPerSize(),
396 | * | position.sizeInUsd(),
397 | * | false // roundUpMagnitude
398 | | );
399 | |
400 | * | fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(
401 | * | fundingFees.latestShortTokenClaimableFundingAmountPerSize,
402 | * | position.shortTokenClaimableFundingAmountPerSize(),
403 | * | position.sizeInUsd(),
404 | * | false // roundUpMagnitude
405 | | );
406 | |
407 | * | return fundingFees;
408 | | }
409 | |
410 | * | function getUiFees(
411 | | DataStore dataStore,
412 | | Price.Props memory collateralTokenPrice,
413 | | uint256 sizeDeltaUsd,
414 | | address uiFeeReceiver
415 | * | ) internal view returns (PositionUiFees memory) {
416 | * | PositionUiFees memory uiFees;
417 | |
418 | * | if (uiFeeReceiver == address(0)) {
419 | * | return uiFees;
420 | | }
421 | |
422 | | uiFees.uiFeeReceiver = uiFeeReceiver;
423 | | uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);
424 | | uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;
425 | |
426 | | return uiFees;
427 | | }
428 | |
429 | | // @dev get position fees after applying referral rebates / discounts
430 | | // @param dataStore DataStore
431 | | // @param referralStorage IReferralStorage
432 | | // @param collateralTokenPrice the price of the position's collateralToken
433 | | // @param the position's account
434 | | // @param market the position's market
435 | | // @param sizeDeltaUsd the change in position size
436 | | // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool)
437 | * | function getPositionFeesAfterReferral(
438 | | DataStore dataStore,
439 | | IReferralStorage referralStorage,
440 | | Price.Props memory collateralTokenPrice,
441 | | bool forPositiveImpact,
442 | | address account,
443 | | address market,
444 | | uint256 sizeDeltaUsd
445 | * | ) internal view returns (PositionFees memory) {
446 | * | PositionFees memory fees;
447 | |
448 | * | fees.collateralTokenPrice = collateralTokenPrice;
449 | |
450 | * | fees.referral.trader = account;
451 | |
452 | * | (
453 | * | fees.referral.referralCode,
454 | * | fees.referral.affiliate,
455 | * | fees.referral.totalRebateFactor,
456 | * | fees.referral.traderDiscountFactor
457 | * | ) = ReferralUtils.getReferralInfo(referralStorage, account);
458 | |
459 | | // note that since it is possible to incur both positive and negative price impact values
460 | | // and the negative price impact factor may be larger than the positive impact factor
461 | | // it is possible for the balance to be improved overall but for the price impact to still be negative
462 | | // in this case the fee factor for the negative price impact would be charged
463 | | // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue
464 | * | fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, forPositiveImpact));
465 | * | fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;
466 | |
467 | * | fees.referral.totalRebateAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.totalRebateFactor);
468 | * | fees.referral.traderDiscountAmount = Precision.applyFactor(fees.referral.totalRebateAmount, fees.referral.traderDiscountFactor);
469 | * | fees.referral.affiliateRewardAmount = fees.referral.totalRebateAmount - fees.referral.traderDiscountAmount;
470 | |
471 | * | fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.totalRebateAmount;
472 | |
473 | * | fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);
474 | * | fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);
475 | * | fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;
476 | |
477 | * | return fees;
478 | | }
479 | |
480 | | }
481 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/PricingUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "prb-math/contracts/PRBMathUD60x18.sol";
6 | |
7 | | import "../utils/Calc.sol";
8 | | import "../utils/Precision.sol";
9 | | import "../market/MarketUtils.sol";
10 | |
11 | | // @title PricingUtils
12 | | // @dev Library for pricing functions
13 | | //
14 | | // Price impact is calculated as:
15 | | //
16 | | // ```
17 | | // (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2)
18 | | // ```
19 | | //
20 | | // For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the
21 | | // difference in the worth of the long tokens and short tokens.
22 | | //
23 | | // For example:
24 | | //
25 | | // - A pool has 10 long tokens, each long token is worth $5000
26 | | // - The pool also has 50,000 short tokens, each short token is worth $1
27 | | // - The `price impact exponent` is set to 2 and `price impact factor` is set
28 | | // to `0.01 / 50,000`
29 | | // - The pool is equally balanced with $50,000 of long tokens and $50,000 of
30 | | // short tokens
31 | | // - If a user deposits 10 long tokens, the pool would now have $100,000 of long
32 | | // tokens and $50,000 of short tokens
33 | | // - The change in imbalance would be from $0 to -$50,000
34 | | // - There would be negative price impact charged on the user's deposit,
35 | | // calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500`
36 | | // - If the user now withdraws 5 long tokens, the balance would change
37 | | // from -$50,000 to -$25,000, a net change of +$25,000
38 | | // - There would be a positive price impact rebated to the user in the form of
39 | | // additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375`
40 | | //
41 | | // For position actions (increase / decrease position), imbalance is calculated
42 | | // as the difference in the long and short open interest.
43 | | //
44 | | // `price impact exponents` and `price impact factors` are configured per market
45 | | // and can differ for spot and position actions.
46 | | //
47 | | // The purpose of the price impact is to help reduce the risk of price manipulation,
48 | | // since the contracts use an oracle price which would be an average or median price
49 | | // of multiple reference exchanges. Without a price impact, it may be profitable to
50 | | // manipulate the prices on reference exchanges while executing orders on the contracts.
51 | | //
52 | | // This risk will also be present if the positive and negative price impact values
53 | | // are similar, for that reason the positive price impact should be set to a low
54 | | // value in times of volatility or irregular price movements.
55 | * | library PricingUtils {
56 | | // @dev get the price impact USD if there is no crossover in balance
57 | | // a crossover in balance is for example if the long open interest is larger
58 | | // than the short open interest, and a short position is opened such that the
59 | | // short open interest becomes larger than the long open interest
60 | | // @param initialDiffUsd the initial difference in USD
61 | | // @param nextDiffUsd the next difference in USD
62 | | // @param impactFactor the impact factor
63 | | // @param impactExponentFactor the impact exponent factor
64 | * | function getPriceImpactUsdForSameSideRebalance(
65 | | uint256 initialDiffUsd,
66 | | uint256 nextDiffUsd,
67 | | uint256 impactFactor,
68 | | uint256 impactExponentFactor
69 | * | ) internal pure returns (int256) {
70 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
71 | |
72 | * | uint256 deltaDiffUsd = Calc.diff(
73 | * | applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),
74 | * | applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)
75 | | );
76 | |
77 | * | int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, hasPositiveImpact);
78 | |
79 | * | return priceImpactUsd;
80 | | }
81 | |
82 | | // @dev get the price impact USD if there is a crossover in balance
83 | | // a crossover in balance is for example if the long open interest is larger
84 | | // than the short open interest, and a short position is opened such that the
85 | | // short open interest becomes larger than the long open interest
86 | | // @param initialDiffUsd the initial difference in USD
87 | | // @param nextDiffUsd the next difference in USD
88 | | // @param hasPositiveImpact whether there is a positive impact on balance
89 | | // @param impactFactor the impact factor
90 | | // @param impactExponentFactor the impact exponent factor
91 | * | function getPriceImpactUsdForCrossoverRebalance(
92 | | uint256 initialDiffUsd,
93 | | uint256 nextDiffUsd,
94 | | uint256 positiveImpactFactor,
95 | | uint256 negativeImpactFactor,
96 | | uint256 impactExponentFactor
97 | * | ) internal pure returns (int256) {
98 | * | uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);
99 | * | uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);
100 | * | uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);
101 | |
102 | * | int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);
103 | |
104 | * | return priceImpactUsd;
105 | | }
106 | |
107 | | // @dev apply the impact factor calculation to a USD diff value
108 | | // @param diffUsd the difference in USD
109 | | // @param impactFactor the impact factor
110 | | // @param impactExponentFactor the impact exponent factor
111 | * | function applyImpactFactor(
112 | | uint256 diffUsd,
113 | | uint256 impactFactor,
114 | | uint256 impactExponentFactor
115 | * | ) internal pure returns (uint256) {
116 | * | uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);
117 | * | return Precision.applyFactor(exponentValue, impactFactor);
118 | | }
119 | | }
120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/SwapPricingUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../market/MarketUtils.sol";
8 | |
9 | | import "../utils/Precision.sol";
10 | | import "../utils/Calc.sol";
11 | |
12 | | import "./PricingUtils.sol";
13 | | import "./ISwapPricingUtils.sol";
14 | |
15 | | // @title SwapPricingUtils
16 | | // @dev Library for pricing functions
17 | * | library SwapPricingUtils {
18 | | using SignedMath for int256;
19 | | using SafeCast for uint256;
20 | | using SafeCast for int256;
21 | |
22 | | using EventUtils for EventUtils.AddressItems;
23 | | using EventUtils for EventUtils.UintItems;
24 | | using EventUtils for EventUtils.IntItems;
25 | | using EventUtils for EventUtils.BoolItems;
26 | | using EventUtils for EventUtils.Bytes32Items;
27 | | using EventUtils for EventUtils.BytesItems;
28 | | using EventUtils for EventUtils.StringItems;
29 | |
30 | | // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to
31 | | // avoid stack too deep errors
32 | | // @param dataStore DataStore
33 | | // @param market the market to check
34 | | // @param tokenA the token to check balance for
35 | | // @param tokenB the token to check balance for
36 | | // @param priceForTokenA the price for tokenA
37 | | // @param priceForTokenB the price for tokenB
38 | | // @param usdDeltaForTokenA the USD change in amount of tokenA
39 | | // @param usdDeltaForTokenB the USD change in amount of tokenB
40 | | struct GetPriceImpactUsdParams {
41 | | DataStore dataStore;
42 | | Market.Props market;
43 | | address tokenA;
44 | | address tokenB;
45 | | uint256 priceForTokenA;
46 | | uint256 priceForTokenB;
47 | | int256 usdDeltaForTokenA;
48 | | int256 usdDeltaForTokenB;
49 | | bool includeVirtualInventoryImpact;
50 | | }
51 | |
52 | | struct EmitSwapInfoParams {
53 | | bytes32 orderKey;
54 | | address market;
55 | | address receiver;
56 | | address tokenIn;
57 | | address tokenOut;
58 | | uint256 tokenInPrice;
59 | | uint256 tokenOutPrice;
60 | | uint256 amountIn;
61 | | uint256 amountInAfterFees;
62 | | uint256 amountOut;
63 | | int256 priceImpactUsd;
64 | | int256 priceImpactAmount;
65 | | int256 tokenInPriceImpactAmount;
66 | | }
67 | |
68 | | // @dev PoolParams struct to contain pool values
69 | | // @param poolUsdForTokenA the USD value of tokenA in the pool
70 | | // @param poolUsdForTokenB the USD value of tokenB in the pool
71 | | // @param nextPoolUsdForTokenA the next USD value of tokenA in the pool
72 | | // @param nextPoolUsdForTokenB the next USD value of tokenB in the pool
73 | | struct PoolParams {
74 | | uint256 poolUsdForTokenA;
75 | | uint256 poolUsdForTokenB;
76 | | uint256 nextPoolUsdForTokenA;
77 | | uint256 nextPoolUsdForTokenB;
78 | | }
79 | |
80 | | // @dev SwapFees struct to contain swap fee values
81 | | // @param feeReceiverAmount the fee amount for the fee receiver
82 | | // @param feeAmountForPool the fee amount for the pool
83 | | // @param amountAfterFees the output amount after fees
84 | | struct SwapFees {
85 | | uint256 feeReceiverAmount;
86 | | uint256 feeAmountForPool;
87 | | uint256 amountAfterFees;
88 | |
89 | | address uiFeeReceiver;
90 | | uint256 uiFeeReceiverFactor;
91 | | uint256 uiFeeAmount;
92 | | }
93 | |
94 | | // @dev get the price impact in USD
95 | | //
96 | | // note that there will be some difference between the pool amounts used for
97 | | // calculating the price impact and fees vs the actual pool amounts after the
98 | | // swap is done, since the pool amounts will be increased / decreased by an amount
99 | | // after factoring in the calculated price impact and fees
100 | | //
101 | | // since the calculations are based on the real-time prices values of the tokens
102 | | // if a token price increases, the pool will incentivise swapping out more of that token
103 | | // this is useful if prices are ranging, if prices are strongly directional, the pool may
104 | | // be selling tokens as the token price increases
105 | | //
106 | | // @param params GetPriceImpactUsdParams
107 | | //
108 | | // @return the price impact in USD
109 | * | function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) {
110 | * | PoolParams memory poolParams = getNextPoolAmountsUsd(params);
111 | |
112 | * | int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market, poolParams);
113 | |
114 | | // the virtual price impact calculation is skipped if the price impact
115 | | // is positive since the action is helping to balance the pool
116 | | //
117 | | // in case two virtual pools are unbalanced in a different direction
118 | | // e.g. pool0 has more WNT than USDC while pool1 has less WNT
119 | | // than USDT
120 | | // not skipping the virtual price impact calculation would lead to
121 | | // a negative price impact for any trade on either pools and would
122 | | // disincentivise the balancing of pools
123 | * | if (priceImpactUsd >= 0) { return priceImpactUsd; }
124 | |
125 | | if (!params.includeVirtualInventoryImpact) {
126 | | return priceImpactUsd;
127 | | }
128 | |
129 | | // note that the virtual pool for the long token / short token may be different across pools
130 | | // e.g. ETH/USDC, ETH/USDT would have USDC and USDT as the short tokens
131 | | // the short token amount is multiplied by the price of the token in the current pool, e.g. if the swap
132 | | // is for the ETH/USDC pool, the combined USDC and USDT short token amounts is multiplied by the price of
133 | | // USDC to calculate the price impact, this should be reasonable most of the time unless there is a
134 | | // large depeg of one of the tokens, in which case it may be necessary to remove that market from being a virtual
135 | | // market, removal of virtual markets may lead to incorrect virtual token accounting, the feature to correct for
136 | | // this can be added if needed
137 | | (bool hasVirtualInventory, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils.getVirtualInventoryForSwaps(
138 | | params.dataStore,
139 | | params.market.marketToken
140 | | );
141 | |
142 | | if (!hasVirtualInventory) {
143 | | return priceImpactUsd;
144 | | }
145 | |
146 | | uint256 virtualPoolAmountForTokenA;
147 | | uint256 virtualPoolAmountForTokenB;
148 | |
149 | | if (params.tokenA == params.market.longToken) {
150 | | virtualPoolAmountForTokenA = virtualPoolAmountForLongToken;
151 | | virtualPoolAmountForTokenB = virtualPoolAmountForShortToken;
152 | | } else {
153 | | virtualPoolAmountForTokenA = virtualPoolAmountForShortToken;
154 | | virtualPoolAmountForTokenB = virtualPoolAmountForLongToken;
155 | | }
156 | |
157 | | PoolParams memory poolParamsForVirtualInventory = getNextPoolAmountsParams(
158 | | params,
159 | | virtualPoolAmountForTokenA,
160 | | virtualPoolAmountForTokenB
161 | | );
162 | |
163 | | int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market, poolParamsForVirtualInventory);
164 | |
165 | | return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd;
166 | | }
167 | |
168 | | // @dev get the price impact in USD
169 | | // @param dataStore DataStore
170 | | // @param market the trading market
171 | | // @param poolParams PoolParams
172 | | // @return the price impact in USD
173 | * | function _getPriceImpactUsd(DataStore dataStore, Market.Props memory market, PoolParams memory poolParams) internal view returns (int256) {
174 | * | uint256 initialDiffUsd = Calc.diff(poolParams.poolUsdForTokenA, poolParams.poolUsdForTokenB);
175 | * | uint256 nextDiffUsd = Calc.diff(poolParams.nextPoolUsdForTokenA, poolParams.nextPoolUsdForTokenB);
176 | |
177 | | // check whether an improvement in balance comes from causing the balance to switch sides
178 | | // for example, if there is $2000 of ETH and $1000 of USDC in the pool
179 | | // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not
180 | | // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case
181 | * | bool isSameSideRebalance = (poolParams.poolUsdForTokenA <= poolParams.poolUsdForTokenB) == (poolParams.nextPoolUsdForTokenA <= poolParams.nextPoolUsdForTokenB);
182 | * | uint256 impactExponentFactor = dataStore.getUint(Keys.swapImpactExponentFactorKey(market.marketToken));
183 | |
184 | * | if (isSameSideRebalance) {
185 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
186 | * | uint256 impactFactor = MarketUtils.getAdjustedSwapImpactFactor(dataStore, market.marketToken, hasPositiveImpact);
187 | |
188 | * | return PricingUtils.getPriceImpactUsdForSameSideRebalance(
189 | * | initialDiffUsd,
190 | * | nextDiffUsd,
191 | * | impactFactor,
192 | * | impactExponentFactor
193 | | );
194 | | } else {
195 | * | (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedSwapImpactFactors(dataStore, market.marketToken);
196 | |
197 | * | return PricingUtils.getPriceImpactUsdForCrossoverRebalance(
198 | * | initialDiffUsd,
199 | * | nextDiffUsd,
200 | * | positiveImpactFactor,
201 | * | negativeImpactFactor,
202 | * | impactExponentFactor
203 | | );
204 | | }
205 | | }
206 | |
207 | | // @dev get the next pool amounts in USD
208 | | // @param params GetPriceImpactUsdParams
209 | | // @return PoolParams
210 | * | function getNextPoolAmountsUsd(
211 | | GetPriceImpactUsdParams memory params
212 | * | ) internal view returns (PoolParams memory) {
213 | * | uint256 poolAmountForTokenA = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenA);
214 | * | uint256 poolAmountForTokenB = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenB);
215 | |
216 | * | return getNextPoolAmountsParams(
217 | * | params,
218 | * | poolAmountForTokenA,
219 | * | poolAmountForTokenB
220 | | );
221 | | }
222 | |
223 | * | function getNextPoolAmountsParams(
224 | | GetPriceImpactUsdParams memory params,
225 | | uint256 poolAmountForTokenA,
226 | | uint256 poolAmountForTokenB
227 | * | ) internal pure returns (PoolParams memory) {
228 | * | uint256 poolUsdForTokenA = poolAmountForTokenA * params.priceForTokenA;
229 | * | uint256 poolUsdForTokenB = poolAmountForTokenB * params.priceForTokenB;
230 | |
231 | * | if (params.usdDeltaForTokenA < 0 && (-params.usdDeltaForTokenA).toUint256() > poolUsdForTokenA) {
232 | | revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenA, poolUsdForTokenA);
233 | | }
234 | |
235 | * | if (params.usdDeltaForTokenB < 0 && (-params.usdDeltaForTokenB).toUint256() > poolUsdForTokenB) {
236 | * | revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenB, poolUsdForTokenB);
237 | | }
238 | |
239 | * | uint256 nextPoolUsdForTokenA = Calc.sumReturnUint256(poolUsdForTokenA, params.usdDeltaForTokenA);
240 | * | uint256 nextPoolUsdForTokenB = Calc.sumReturnUint256(poolUsdForTokenB, params.usdDeltaForTokenB);
241 | |
242 | * | PoolParams memory poolParams = PoolParams(
243 | * | poolUsdForTokenA,
244 | * | poolUsdForTokenB,
245 | * | nextPoolUsdForTokenA,
246 | * | nextPoolUsdForTokenB
247 | | );
248 | |
249 | * | return poolParams;
250 | | }
251 | |
252 | | // @dev get the swap fees
253 | | // @param dataStore DataStore
254 | | // @param marketToken the address of the market token
255 | | // @param amount the total swap fee amount
256 | * | function getSwapFees(
257 | | DataStore dataStore,
258 | | address marketToken,
259 | | uint256 amount,
260 | | bool forPositiveImpact,
261 | | address uiFeeReceiver,
262 | | ISwapPricingUtils.SwapPricingType swapPricingType
263 | * | ) internal view returns (SwapFees memory) {
264 | * | SwapFees memory fees;
265 | |
266 | | // note that since it is possible to incur both positive and negative price impact values
267 | | // and the negative price impact factor may be larger than the positive impact factor
268 | | // it is possible for the balance to be improved overall but for the price impact to still be negative
269 | | // in this case the fee factor for the negative price impact would be charged
270 | | // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue
271 | * | uint256 feeFactor;
272 | |
273 | * | if (swapPricingType == ISwapPricingUtils.SwapPricingType.TwoStep) {
274 | * | feeFactor = dataStore.getUint(Keys.swapFeeFactorKey(marketToken, forPositiveImpact));
275 | * | } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Shift) {
276 | | // empty branch as feeFactor is already zero
277 | * | } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Atomic) {
278 | * | feeFactor = dataStore.getUint(Keys.atomicSwapFeeFactorKey(marketToken));
279 | | }
280 | |
281 | * | uint256 swapFeeReceiverFactor = dataStore.getUint(Keys.SWAP_FEE_RECEIVER_FACTOR);
282 | |
283 | * | uint256 feeAmount = Precision.applyFactor(amount, feeFactor);
284 | |
285 | * | fees.feeReceiverAmount = Precision.applyFactor(feeAmount, swapFeeReceiverFactor);
286 | * | fees.feeAmountForPool = feeAmount - fees.feeReceiverAmount;
287 | |
288 | * | fees.uiFeeReceiver = uiFeeReceiver;
289 | * | fees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);
290 | * | fees.uiFeeAmount = Precision.applyFactor(amount, fees.uiFeeReceiverFactor);
291 | |
292 | * | fees.amountAfterFees = amount - feeAmount - fees.uiFeeAmount;
293 | |
294 | * | return fees;
295 | | }
296 | |
297 | | // note that the priceImpactUsd may not be entirely accurate since it is the
298 | | // base calculation and the actual price impact may be capped by the available
299 | | // amount in the swap impact pool
300 | * | function emitSwapInfo(
301 | | EventEmitter eventEmitter,
302 | | EmitSwapInfoParams memory params
303 | * | ) internal {
304 | * | EventUtils.EventLogData memory eventData;
305 | |
306 | * | eventData.bytes32Items.initItems(1);
307 | * | eventData.bytes32Items.setItem(0, "orderKey", params.orderKey);
308 | |
309 | * | eventData.addressItems.initItems(4);
310 | * | eventData.addressItems.setItem(0, "market", params.market);
311 | * | eventData.addressItems.setItem(1, "receiver", params.receiver);
312 | * | eventData.addressItems.setItem(2, "tokenIn", params.tokenIn);
313 | * | eventData.addressItems.setItem(3, "tokenOut", params.tokenOut);
314 | |
315 | * | eventData.uintItems.initItems(5);
316 | * | eventData.uintItems.setItem(0, "tokenInPrice", params.tokenInPrice);
317 | * | eventData.uintItems.setItem(1, "tokenOutPrice", params.tokenOutPrice);
318 | * | eventData.uintItems.setItem(2, "amountIn", params.amountIn);
319 | | // note that amountInAfterFees includes negative price impact
320 | * | eventData.uintItems.setItem(3, "amountInAfterFees", params.amountInAfterFees);
321 | * | eventData.uintItems.setItem(4, "amountOut", params.amountOut);
322 | |
323 | * | eventData.intItems.initItems(3);
324 | * | eventData.intItems.setItem(0, "priceImpactUsd", params.priceImpactUsd);
325 | * | eventData.intItems.setItem(1, "priceImpactAmount", params.priceImpactAmount);
326 | * | eventData.intItems.setItem(2, "tokenInPriceImpactAmount", params.tokenInPriceImpactAmount);
327 | |
328 | * | eventEmitter.emitEventLog1(
329 | | "SwapInfo",
330 | * | Cast.toBytes32(params.market),
331 | * | eventData
332 | | );
333 | | }
334 | |
335 | * | function emitSwapFeesCollected(
336 | | EventEmitter eventEmitter,
337 | | bytes32 tradeKey,
338 | | address market,
339 | | address token,
340 | | uint256 tokenPrice,
341 | | bytes32 swapFeeType,
342 | | SwapFees memory fees
343 | * | ) internal {
344 | * | EventUtils.EventLogData memory eventData;
345 | |
346 | * | eventData.bytes32Items.initItems(2);
347 | * | eventData.bytes32Items.setItem(0, "tradeKey", tradeKey);
348 | * | eventData.bytes32Items.setItem(1, "swapFeeType", swapFeeType);
349 | |
350 | * | eventData.addressItems.initItems(3);
351 | * | eventData.addressItems.setItem(0, "uiFeeReceiver", fees.uiFeeReceiver);
352 | * | eventData.addressItems.setItem(1, "market", market);
353 | * | eventData.addressItems.setItem(2, "token", token);
354 | |
355 | * | eventData.uintItems.initItems(6);
356 | * | eventData.uintItems.setItem(0, "tokenPrice", tokenPrice);
357 | * | eventData.uintItems.setItem(1, "feeReceiverAmount", fees.feeReceiverAmount);
358 | * | eventData.uintItems.setItem(2, "feeAmountForPool", fees.feeAmountForPool);
359 | * | eventData.uintItems.setItem(3, "amountAfterFees", fees.amountAfterFees);
360 | * | eventData.uintItems.setItem(4, "uiFeeReceiverFactor", fees.uiFeeReceiverFactor);
361 | * | eventData.uintItems.setItem(5, "uiFeeAmount", fees.uiFeeAmount);
362 | |
363 | * | eventEmitter.emitEventLog1(
364 | | "SwapFeesCollected",
365 | * | Cast.toBytes32(market),
366 | * | eventData
367 | | );
368 | | }
369 | | }
370 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/Reader.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | |
7 | | import "../market/MarketStoreUtils.sol";
8 | |
9 | | import "../deposit/DepositStoreUtils.sol";
10 | | import "../withdrawal/WithdrawalStoreUtils.sol";
11 | | import "../shift/ShiftStoreUtils.sol";
12 | |
13 | | import "../position/Position.sol";
14 | | import "../position/PositionUtils.sol";
15 | | import "../position/PositionStoreUtils.sol";
16 | |
17 | | import "../order/OrderStoreUtils.sol";
18 | |
19 | | import "../market/MarketUtils.sol";
20 | | import "../market/Market.sol";
21 | |
22 | | import "../adl/AdlUtils.sol";
23 | |
24 | | import "./ReaderUtils.sol";
25 | | import "./ReaderDepositUtils.sol";
26 | | import "./ReaderWithdrawalUtils.sol";
27 | |
28 | | // @title Reader
29 | | // @dev Library for read functions
30 | * | contract Reader {
31 | | using SafeCast for uint256;
32 | | using Position for Position.Props;
33 | |
34 | * | function getMarket(DataStore dataStore, address key) external view returns (Market.Props memory) {
35 | * | return MarketStoreUtils.get(dataStore, key);
36 | | }
37 | |
38 | | function getMarketBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {
39 | | return MarketStoreUtils.getBySalt(dataStore, salt);
40 | | }
41 | |
42 | | function getDeposit(DataStore dataStore, bytes32 key) external view returns (Deposit.Props memory) {
43 | | return DepositStoreUtils.get(dataStore, key);
44 | | }
45 | |
46 | * | function getWithdrawal(DataStore dataStore, bytes32 key) external view returns (Withdrawal.Props memory) {
47 | * | return WithdrawalStoreUtils.get(dataStore, key);
48 | | }
49 | |
50 | | function getShift(DataStore dataStore, bytes32 key) external view returns (Shift.Props memory) {
51 | | return ShiftStoreUtils.get(dataStore, key);
52 | | }
53 | |
54 | | function getPosition(DataStore dataStore, bytes32 key) external view returns (Position.Props memory) {
55 | | return PositionStoreUtils.get(dataStore, key);
56 | | }
57 | |
58 | | function getOrder(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) {
59 | | return OrderStoreUtils.get(dataStore, key);
60 | | }
61 | |
62 | | function getPositionPnlUsd(
63 | | DataStore dataStore,
64 | | Market.Props memory market,
65 | | MarketUtils.MarketPrices memory prices,
66 | | bytes32 positionKey,
67 | | uint256 sizeDeltaUsd
68 | | ) external view returns (int256, int256, uint256) {
69 | | Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey);
70 | |
71 | | return PositionUtils.getPositionPnlUsd(dataStore, market, prices, position, sizeDeltaUsd);
72 | | }
73 | |
74 | * | function getAccountPositions(
75 | | DataStore dataStore,
76 | | address account,
77 | | uint256 start,
78 | | uint256 end
79 | * | ) external view returns (Position.Props[] memory) {
80 | * | bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end);
81 | * | Position.Props[] memory positions = new Position.Props[](positionKeys.length);
82 | * | for (uint256 i; i < positionKeys.length; i++) {
83 | * | bytes32 positionKey = positionKeys[i];
84 | * | positions[i] = PositionStoreUtils.get(dataStore, positionKey);
85 | | }
86 | |
87 | * | return positions;
88 | | }
89 | |
90 | | function getAccountPositionInfoList(
91 | | DataStore dataStore,
92 | | IReferralStorage referralStorage,
93 | | bytes32[] memory positionKeys,
94 | | MarketUtils.MarketPrices[] memory prices,
95 | | address uiFeeReceiver
96 | | ) external view returns (ReaderUtils.PositionInfo[] memory) {
97 | | ReaderUtils.PositionInfo[] memory positionInfoList = new ReaderUtils.PositionInfo[](positionKeys.length);
98 | | for (uint256 i; i < positionKeys.length; i++) {
99 | | bytes32 positionKey = positionKeys[i];
100 | | positionInfoList[i] = getPositionInfo(
101 | | dataStore,
102 | | referralStorage,
103 | | positionKey,
104 | | prices[i],
105 | | 0, // sizeDeltaUsd
106 | | uiFeeReceiver,
107 | | true // usePositionSizeAsSizeDeltaUsd
108 | | );
109 | | }
110 | |
111 | | return positionInfoList;
112 | | }
113 | |
114 | * | function getPositionInfo(
115 | | DataStore dataStore,
116 | | IReferralStorage referralStorage,
117 | | bytes32 positionKey,
118 | | MarketUtils.MarketPrices memory prices,
119 | | uint256 sizeDeltaUsd,
120 | | address uiFeeReceiver,
121 | | bool usePositionSizeAsSizeDeltaUsd
122 | * | ) public view returns (ReaderUtils.PositionInfo memory) {
123 | * | return
124 | * | ReaderUtils.getPositionInfo(
125 | * | dataStore,
126 | * | referralStorage,
127 | * | positionKey,
128 | * | prices,
129 | * | sizeDeltaUsd,
130 | * | uiFeeReceiver,
131 | * | usePositionSizeAsSizeDeltaUsd
132 | | );
133 | | }
134 | |
135 | | function getAccountOrders(
136 | | DataStore dataStore,
137 | | address account,
138 | | uint256 start,
139 | | uint256 end
140 | | ) external view returns (Order.Props[] memory) {
141 | | bytes32[] memory orderKeys = OrderStoreUtils.getAccountOrderKeys(dataStore, account, start, end);
142 | | Order.Props[] memory orders = new Order.Props[](orderKeys.length);
143 | | for (uint256 i; i < orderKeys.length; i++) {
144 | | bytes32 orderKey = orderKeys[i];
145 | | orders[i] = OrderStoreUtils.get(dataStore, orderKey);
146 | | }
147 | |
148 | | return orders;
149 | | }
150 | |
151 | | function getMarkets(DataStore dataStore, uint256 start, uint256 end) external view returns (Market.Props[] memory) {
152 | | address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end);
153 | | Market.Props[] memory markets = new Market.Props[](marketKeys.length);
154 | | for (uint256 i; i < marketKeys.length; i++) {
155 | | address marketKey = marketKeys[i];
156 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);
157 | | markets[i] = market;
158 | | }
159 | |
160 | | return markets;
161 | | }
162 | |
163 | | function getMarketInfoList(
164 | | DataStore dataStore,
165 | | MarketUtils.MarketPrices[] memory marketPricesList,
166 | | uint256 start,
167 | | uint256 end
168 | | ) external view returns (ReaderUtils.MarketInfo[] memory) {
169 | | address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end);
170 | | ReaderUtils.MarketInfo[] memory marketInfoList = new ReaderUtils.MarketInfo[](marketKeys.length);
171 | | for (uint256 i; i < marketKeys.length; i++) {
172 | | MarketUtils.MarketPrices memory prices = marketPricesList[i];
173 | | address marketKey = marketKeys[i];
174 | | marketInfoList[i] = getMarketInfo(dataStore, prices, marketKey);
175 | | }
176 | |
177 | | return marketInfoList;
178 | | }
179 | |
180 | * | function getMarketInfo(
181 | | DataStore dataStore,
182 | | MarketUtils.MarketPrices memory prices,
183 | | address marketKey
184 | * | ) public view returns (ReaderUtils.MarketInfo memory) {
185 | * | return ReaderUtils.getMarketInfo(
186 | * | dataStore,
187 | * | prices,
188 | * | marketKey
189 | | );
190 | | }
191 | |
192 | | function getMarketTokenPrice(
193 | | DataStore dataStore,
194 | | Market.Props memory market,
195 | | Price.Props memory indexTokenPrice,
196 | | Price.Props memory longTokenPrice,
197 | | Price.Props memory shortTokenPrice,
198 | | bytes32 pnlFactorType,
199 | | bool maximize
200 | | ) external view returns (int256, MarketPoolValueInfo.Props memory) {
201 | | return
202 | | MarketUtils.getMarketTokenPrice(
203 | | dataStore,
204 | | market,
205 | | indexTokenPrice,
206 | | longTokenPrice,
207 | | shortTokenPrice,
208 | | pnlFactorType,
209 | | maximize
210 | | );
211 | | }
212 | |
213 | | function getNetPnl(
214 | | DataStore dataStore,
215 | | Market.Props memory market,
216 | | Price.Props memory indexTokenPrice,
217 | | bool maximize
218 | | ) external view returns (int256) {
219 | | return MarketUtils.getNetPnl(dataStore, market, indexTokenPrice, maximize);
220 | | }
221 | |
222 | | function getPnl(
223 | | DataStore dataStore,
224 | | Market.Props memory market,
225 | | Price.Props memory indexTokenPrice,
226 | | bool isLong,
227 | | bool maximize
228 | | ) external view returns (int256) {
229 | | return MarketUtils.getPnl(dataStore, market, indexTokenPrice, isLong, maximize);
230 | | }
231 | |
232 | | function getOpenInterestWithPnl(
233 | | DataStore dataStore,
234 | | Market.Props memory market,
235 | | Price.Props memory indexTokenPrice,
236 | | bool isLong,
237 | | bool maximize
238 | | ) external view returns (int256) {
239 | | return MarketUtils.getOpenInterestWithPnl(dataStore, market, indexTokenPrice, isLong, maximize);
240 | | }
241 | |
242 | | function getPnlToPoolFactor(
243 | | DataStore dataStore,
244 | | address marketAddress,
245 | | MarketUtils.MarketPrices memory prices,
246 | | bool isLong,
247 | | bool maximize
248 | | ) external view returns (int256) {
249 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
250 | | return MarketUtils.getPnlToPoolFactor(dataStore, market, prices, isLong, maximize);
251 | | }
252 | |
253 | * | function getSwapAmountOut(
254 | | DataStore dataStore,
255 | | Market.Props memory market,
256 | | MarketUtils.MarketPrices memory prices,
257 | | address tokenIn,
258 | | uint256 amountIn,
259 | | address uiFeeReceiver
260 | * | ) external view returns (uint256, int256, SwapPricingUtils.SwapFees memory fees) {
261 | * | return ReaderPricingUtils.getSwapAmountOut(dataStore, market, prices, tokenIn, amountIn, uiFeeReceiver);
262 | | }
263 | |
264 | | function getExecutionPrice(
265 | | DataStore dataStore,
266 | | address marketKey,
267 | | Price.Props memory indexTokenPrice,
268 | | uint256 positionSizeInUsd,
269 | | uint256 positionSizeInTokens,
270 | | int256 sizeDeltaUsd,
271 | | bool isLong
272 | | ) external view returns (ReaderPricingUtils.ExecutionPriceResult memory) {
273 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);
274 | | return
275 | | ReaderPricingUtils.getExecutionPrice(
276 | | dataStore,
277 | | market,
278 | | indexTokenPrice,
279 | | positionSizeInUsd,
280 | | positionSizeInTokens,
281 | | sizeDeltaUsd,
282 | | isLong
283 | | );
284 | | }
285 | |
286 | | function getSwapPriceImpact(
287 | | DataStore dataStore,
288 | | address marketKey,
289 | | address tokenIn,
290 | | address tokenOut,
291 | | uint256 amountIn,
292 | | Price.Props memory tokenInPrice,
293 | | Price.Props memory tokenOutPrice
294 | | ) external view returns (int256, int256, int256) {
295 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);
296 | | return
297 | | ReaderPricingUtils.getSwapPriceImpact(
298 | | dataStore,
299 | | market,
300 | | tokenIn,
301 | | tokenOut,
302 | | amountIn,
303 | | tokenInPrice,
304 | | tokenOutPrice
305 | | );
306 | | }
307 | |
308 | | function getAdlState(
309 | | DataStore dataStore,
310 | | address market,
311 | | bool isLong,
312 | | MarketUtils.MarketPrices memory prices
313 | | ) external view returns (uint256, bool, int256, uint256) {
314 | | uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong);
315 | | Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market);
316 | |
317 | | (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded(
318 | | dataStore,
319 | | _market,
320 | | prices,
321 | | isLong,
322 | | Keys.MAX_PNL_FACTOR_FOR_ADL
323 | | );
324 | |
325 | | return (latestAdlTime, shouldEnableAdl, pnlToPoolFactor, maxPnlFactor);
326 | | }
327 | |
328 | | function getDepositAmountOut(
329 | | DataStore dataStore,
330 | | Market.Props memory market,
331 | | MarketUtils.MarketPrices memory prices,
332 | | uint256 longTokenAmount,
333 | | uint256 shortTokenAmount,
334 | | address uiFeeReceiver,
335 | | ISwapPricingUtils.SwapPricingType swapPricingType,
336 | | bool includeVirtualInventoryImpact
337 | | ) external view returns (uint256) {
338 | | return ReaderDepositUtils.getDepositAmountOut(
339 | | dataStore,
340 | | market,
341 | | prices,
342 | | longTokenAmount,
343 | | shortTokenAmount,
344 | | uiFeeReceiver,
345 | | swapPricingType,
346 | | includeVirtualInventoryImpact
347 | | );
348 | | }
349 | |
350 | | function getWithdrawalAmountOut(
351 | | DataStore dataStore,
352 | | Market.Props memory market,
353 | | MarketUtils.MarketPrices memory prices,
354 | | uint256 marketTokenAmount,
355 | | address uiFeeReceiver,
356 | | ISwapPricingUtils.SwapPricingType swapPricingType
357 | | ) external view returns (uint256, uint256) {
358 | | return ReaderWithdrawalUtils.getWithdrawalAmountOut(
359 | | dataStore,
360 | | market,
361 | | prices,
362 | | marketTokenAmount,
363 | | uiFeeReceiver,
364 | | swapPricingType
365 | | );
366 | | }
367 | | }
368 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderDepositUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../data/Keys.sol";
8 | |
9 | | import "../market/MarketStoreUtils.sol";
10 | |
11 | | import "../deposit/DepositStoreUtils.sol";
12 | | import "../withdrawal/WithdrawalStoreUtils.sol";
13 | |
14 | | import "../position/Position.sol";
15 | | import "../position/PositionUtils.sol";
16 | | import "../position/PositionStoreUtils.sol";
17 | | import "../position/IncreasePositionUtils.sol";
18 | | import "../position/DecreasePositionUtils.sol";
19 | |
20 | | import "../order/OrderStoreUtils.sol";
21 | |
22 | | import "../market/MarketUtils.sol";
23 | | import "../market/Market.sol";
24 | | import "./ReaderPricingUtils.sol";
25 | |
26 | * | library ReaderDepositUtils {
27 | | using SignedMath for int256;
28 | | using SafeCast for uint256;
29 | | using SafeCast for int256;
30 | | using Price for Price.Props;
31 | | using Position for Position.Props;
32 | | using Order for Order.Props;
33 | |
34 | | struct GetDepositAmountOutForSingleTokenParams {
35 | | DataStore dataStore;
36 | | Market.Props market;
37 | | MarketUtils.MarketPrices prices;
38 | | address tokenIn;
39 | | Price.Props tokenInPrice;
40 | | address tokenOut;
41 | | Price.Props tokenOutPrice;
42 | | uint256 amount;
43 | | int256 priceImpactUsd;
44 | | address uiFeeReceiver;
45 | | ISwapPricingUtils.SwapPricingType swapPricingType;
46 | | }
47 | |
48 | * | function getDepositAmountOut(
49 | | DataStore dataStore,
50 | | Market.Props memory market,
51 | | MarketUtils.MarketPrices memory prices,
52 | | uint256 longTokenAmount,
53 | | uint256 shortTokenAmount,
54 | | address uiFeeReceiver,
55 | | ISwapPricingUtils.SwapPricingType swapPricingType,
56 | | bool includeVirtualInventoryImpact
57 | * | ) internal view returns (uint256) {
58 | * | uint256 longTokenUsd = longTokenAmount * prices.longTokenPrice.midPrice();
59 | * | uint256 shortTokenUsd = shortTokenAmount * prices.shortTokenPrice.midPrice();
60 | * | int256 priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
61 | * | SwapPricingUtils.GetPriceImpactUsdParams(
62 | * | dataStore,
63 | * | market,
64 | * | market.longToken,
65 | * | market.shortToken,
66 | * | prices.longTokenPrice.midPrice(),
67 | * | prices.shortTokenPrice.midPrice(),
68 | * | longTokenUsd.toInt256(),
69 | * | shortTokenUsd.toInt256(),
70 | * | includeVirtualInventoryImpact
71 | | )
72 | | );
73 | |
74 | * | uint256 mintAmount;
75 | |
76 | * | mintAmount += getDepositAmountOutForSingleToken(
77 | * | GetDepositAmountOutForSingleTokenParams(
78 | * | dataStore,
79 | * | market,
80 | * | prices,
81 | * | market.longToken,
82 | * | prices.longTokenPrice,
83 | * | market.shortToken,
84 | * | prices.shortTokenPrice,
85 | * | longTokenAmount,
86 | * | Precision.mulDiv(priceImpactUsd, longTokenUsd, longTokenUsd + shortTokenUsd),
87 | * | uiFeeReceiver,
88 | * | swapPricingType
89 | | )
90 | | );
91 | |
92 | * | mintAmount += getDepositAmountOutForSingleToken(
93 | * | GetDepositAmountOutForSingleTokenParams(
94 | * | dataStore,
95 | * | market,
96 | * | prices,
97 | * | market.shortToken,
98 | * | prices.shortTokenPrice,
99 | * | market.longToken,
100 | * | prices.longTokenPrice,
101 | * | shortTokenAmount,
102 | * | Precision.mulDiv(priceImpactUsd, shortTokenUsd, longTokenUsd + shortTokenUsd),
103 | * | uiFeeReceiver,
104 | * | swapPricingType
105 | | )
106 | | );
107 | |
108 | * | return mintAmount;
109 | | }
110 | |
111 | * | function getDepositAmountOutForSingleToken(
112 | | GetDepositAmountOutForSingleTokenParams memory params
113 | * | ) internal view returns (uint256) {
114 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(
115 | * | params.dataStore,
116 | * | params.market.marketToken,
117 | * | params.amount,
118 | * | params.priceImpactUsd > 0, // forPositiveImpact
119 | * | params.uiFeeReceiver, // uiFeeReceiver
120 | * | params.swapPricingType
121 | | );
122 | |
123 | * | uint256 mintAmount;
124 | |
125 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
126 | * | params.dataStore,
127 | * | params.market,
128 | * | params.prices.indexTokenPrice,
129 | * | params.prices.longTokenPrice,
130 | * | params.prices.shortTokenPrice,
131 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS,
132 | * | true
133 | | );
134 | |
135 | * | if (poolValueInfo.poolValue < 0) {
136 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);
137 | | }
138 | |
139 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256();
140 | |
141 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(params.market.marketToken)));
142 | |
143 | * | if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) {
144 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue);
145 | | }
146 | |
147 | * | if (params.priceImpactUsd > 0 && marketTokensSupply == 0) {
148 | | params.priceImpactUsd = 0;
149 | | }
150 | |
151 | * | if (params.priceImpactUsd > 0) {
152 | | (int256 positiveImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
153 | | params.dataStore,
154 | | params.market.marketToken,
155 | | params.tokenOut,
156 | | params.tokenOutPrice,
157 | | params.priceImpactUsd
158 | | );
159 | |
160 | | mintAmount += MarketUtils.usdToMarketTokenAmount(
161 | | positiveImpactAmount.toUint256() * params.tokenOutPrice.max,
162 | | poolValue,
163 | | marketTokensSupply
164 | | );
165 | | }
166 | |
167 | * | if (params.priceImpactUsd < 0) {
168 | | (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
169 | | params.dataStore,
170 | | params.market.marketToken,
171 | | params.tokenIn,
172 | | params.tokenInPrice,
173 | | params.priceImpactUsd
174 | | );
175 | |
176 | | fees.amountAfterFees -= (-negativeImpactAmount).toUint256();
177 | | }
178 | |
179 | * | mintAmount += MarketUtils.usdToMarketTokenAmount(
180 | * | fees.amountAfterFees * params.tokenInPrice.min,
181 | * | poolValue,
182 | * | marketTokensSupply
183 | | );
184 | |
185 | * | return mintAmount;
186 | | }
187 | | }
188 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderPricingUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../data/Keys.sol";
8 | |
9 | | import "../market/MarketStoreUtils.sol";
10 | |
11 | | import "../deposit/DepositStoreUtils.sol";
12 | | import "../withdrawal/WithdrawalStoreUtils.sol";
13 | |
14 | | import "../position/Position.sol";
15 | | import "../position/PositionUtils.sol";
16 | | import "../position/PositionStoreUtils.sol";
17 | | import "../position/IncreasePositionUtils.sol";
18 | | import "../position/DecreasePositionUtils.sol";
19 | |
20 | | import "../order/OrderStoreUtils.sol";
21 | |
22 | | import "../market/MarketUtils.sol";
23 | | import "../market/Market.sol";
24 | |
25 | | // @title ReaderPricingUtils
26 | * | library ReaderPricingUtils {
27 | | using SignedMath for int256;
28 | | using SafeCast for uint256;
29 | | using SafeCast for int256;
30 | | using Price for Price.Props;
31 | | using Position for Position.Props;
32 | | using Order for Order.Props;
33 | |
34 | | struct ExecutionPriceResult {
35 | | int256 priceImpactUsd;
36 | | uint256 priceImpactDiffUsd;
37 | | uint256 executionPrice;
38 | | }
39 | |
40 | | struct PositionInfo {
41 | | Position.Props position;
42 | | PositionPricingUtils.PositionFees fees;
43 | | ExecutionPriceResult executionPriceResult;
44 | | int256 basePnlUsd;
45 | | int256 pnlAfterPriceImpactUsd;
46 | | }
47 | |
48 | | struct GetPositionInfoCache {
49 | | Market.Props market;
50 | | Price.Props collateralTokenPrice;
51 | | uint256 pendingBorrowingFeeUsd;
52 | | int256 latestLongTokenFundingAmountPerSize;
53 | | int256 latestShortTokenFundingAmountPerSize;
54 | | }
55 | |
56 | | // returns amountOut, price impact, fees
57 | * | function getSwapAmountOut(
58 | | DataStore dataStore,
59 | | Market.Props memory market,
60 | | MarketUtils.MarketPrices memory prices,
61 | | address tokenIn,
62 | | uint256 amountIn,
63 | | address uiFeeReceiver
64 | * | ) internal view returns (uint256, int256, SwapPricingUtils.SwapFees memory) {
65 | * | SwapUtils.SwapCache memory cache;
66 | |
67 | * | if (tokenIn != market.longToken && tokenIn != market.shortToken) {
68 | | revert Errors.InvalidTokenIn(tokenIn, market.marketToken);
69 | | }
70 | |
71 | * | MarketUtils.validateSwapMarket(dataStore, market);
72 | |
73 | * | cache.tokenOut = MarketUtils.getOppositeToken(tokenIn, market);
74 | * | cache.tokenInPrice = MarketUtils.getCachedTokenPrice(tokenIn, market, prices);
75 | * | cache.tokenOutPrice = MarketUtils.getCachedTokenPrice(cache.tokenOut, market, prices);
76 | |
77 | * | int256 priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
78 | * | SwapPricingUtils.GetPriceImpactUsdParams(
79 | * | dataStore,
80 | * | market,
81 | * | tokenIn,
82 | * | cache.tokenOut,
83 | * | cache.tokenInPrice.midPrice(),
84 | * | cache.tokenOutPrice.midPrice(),
85 | * | (amountIn * cache.tokenInPrice.midPrice()).toInt256(),
86 | * | -(amountIn * cache.tokenInPrice.midPrice()).toInt256(),
87 | * | true // includeVirtualInventoryImpact
88 | | )
89 | | );
90 | |
91 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(
92 | * | dataStore,
93 | * | market.marketToken,
94 | * | amountIn,
95 | * | priceImpactUsd > 0, // forPositiveImpact
96 | * | uiFeeReceiver,
97 | * | ISwapPricingUtils.SwapPricingType.TwoStep
98 | | );
99 | |
100 | * | int256 impactAmount;
101 | |
102 | * | if (priceImpactUsd > 0) {
103 | | // when there is a positive price impact factor, additional tokens from the swap impact pool
104 | | // are withdrawn for the user
105 | | // for example, if 50,000 USDC is swapped out and there is a positive price impact
106 | | // an additional 100 USDC may be sent to the user
107 | | // the swap impact pool is decreased by the used amount
108 | |
109 | | cache.amountIn = fees.amountAfterFees;
110 | |
111 | | (impactAmount, cache.cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap(
112 | | dataStore,
113 | | market.marketToken,
114 | | cache.tokenOut,
115 | | cache.tokenOutPrice,
116 | | priceImpactUsd
117 | | );
118 | |
119 | | if (cache.cappedDiffUsd != 0) {
120 | | (cache.tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
121 | | dataStore,
122 | | market.marketToken,
123 | | tokenIn,
124 | | cache.tokenInPrice,
125 | | cache.cappedDiffUsd.toInt256()
126 | | );
127 | |
128 | | // this additional amountIn is already in the Market
129 | | // it is subtracted from the swap impact pool amount
130 | | // and the market pool amount is increased by the updated
131 | | // amountIn below
132 | | cache.amountIn += cache.tokenInPriceImpactAmount.toUint256();
133 | | }
134 | |
135 | | // round amountOut down
136 | | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
137 | | cache.poolAmountOut = cache.amountOut;
138 | |
139 | | cache.amountOut += impactAmount.toUint256();
140 | | } else {
141 | | // when there is a negative price impact factor,
142 | | // less of the input amount is sent to the pool
143 | | // for example, if 10 ETH is swapped in and there is a negative price impact
144 | | // only 9.995 ETH may be swapped in
145 | | // the remaining 0.005 ETH will be stored in the swap impact pool
146 | |
147 | * | (impactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
148 | * | dataStore,
149 | * | market.marketToken,
150 | * | tokenIn,
151 | * | cache.tokenInPrice,
152 | * | priceImpactUsd
153 | | );
154 | |
155 | * | cache.amountIn = fees.amountAfterFees - (-impactAmount).toUint256();
156 | * | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
157 | * | cache.poolAmountOut = cache.amountOut;
158 | | }
159 | |
160 | * | return (cache.amountOut, impactAmount, fees);
161 | | }
162 | |
163 | * | function getExecutionPrice(
164 | | DataStore dataStore,
165 | | Market.Props memory market,
166 | | Price.Props memory indexTokenPrice,
167 | | uint256 positionSizeInUsd,
168 | | uint256 positionSizeInTokens,
169 | | int256 sizeDeltaUsd,
170 | | bool isLong
171 | * | ) internal view returns (ExecutionPriceResult memory) {
172 | * | PositionUtils.UpdatePositionParams memory params;
173 | |
174 | * | params.contracts.dataStore = dataStore;
175 | * | params.market = market;
176 | |
177 | * | params.order.setSizeDeltaUsd(sizeDeltaUsd.abs());
178 | * | params.order.setIsLong(isLong);
179 | |
180 | * | bool isIncrease = sizeDeltaUsd > 0;
181 | * | bool shouldExecutionPriceBeSmaller = isIncrease ? isLong : !isLong;
182 | * | params.order.setAcceptablePrice(shouldExecutionPriceBeSmaller ? type(uint256).max : 0);
183 | |
184 | * | params.position.setSizeInUsd(positionSizeInUsd);
185 | * | params.position.setSizeInTokens(positionSizeInTokens);
186 | * | params.position.setIsLong(isLong);
187 | |
188 | * | ExecutionPriceResult memory result;
189 | |
190 | * | if (sizeDeltaUsd > 0) {
191 | | (result.priceImpactUsd, /* priceImpactAmount */, /* sizeDeltaInTokens */, result.executionPrice) = PositionUtils.getExecutionPriceForIncrease(
192 | | params,
193 | | indexTokenPrice
194 | | );
195 | | } else {
196 | * | (result.priceImpactUsd, result.priceImpactDiffUsd, result.executionPrice) = PositionUtils.getExecutionPriceForDecrease(
197 | * | params,
198 | * | indexTokenPrice
199 | | );
200 | | }
201 | |
202 | * | return result;
203 | | }
204 | |
205 | | function getSwapPriceImpact(
206 | | DataStore dataStore,
207 | | Market.Props memory market,
208 | | address tokenIn,
209 | | address tokenOut,
210 | | uint256 amountIn,
211 | | Price.Props memory tokenInPrice,
212 | | Price.Props memory tokenOutPrice
213 | | ) internal view returns (int256 priceImpactUsdBeforeCap, int256 priceImpactAmount, int256 tokenInPriceImpactAmount) {
214 | | priceImpactUsdBeforeCap = SwapPricingUtils.getPriceImpactUsd(
215 | | SwapPricingUtils.GetPriceImpactUsdParams(
216 | | dataStore,
217 | | market,
218 | | tokenIn,
219 | | tokenOut,
220 | | tokenInPrice.midPrice(),
221 | | tokenOutPrice.midPrice(),
222 | | (amountIn * tokenInPrice.midPrice()).toInt256(),
223 | | -(amountIn * tokenInPrice.midPrice()).toInt256(),
224 | | true // includeVirtualInventoryImpact
225 | | )
226 | | );
227 | |
228 | | if (priceImpactUsdBeforeCap > 0) {
229 | | uint256 cappedDiffUsd;
230 | | (priceImpactAmount, cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap(
231 | | dataStore,
232 | | market.marketToken,
233 | | tokenOut,
234 | | tokenOutPrice,
235 | | priceImpactUsdBeforeCap
236 | | );
237 | |
238 | | if (cappedDiffUsd != 0) {
239 | | (tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
240 | | dataStore,
241 | | market.marketToken,
242 | | tokenIn,
243 | | tokenInPrice,
244 | | cappedDiffUsd.toInt256()
245 | | );
246 | | }
247 | | } else {
248 | | (priceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap(
249 | | dataStore,
250 | | market.marketToken,
251 | | tokenIn,
252 | | tokenInPrice,
253 | | priceImpactUsdBeforeCap
254 | | );
255 | | }
256 | |
257 | | return (priceImpactUsdBeforeCap, priceImpactAmount, tokenInPriceImpactAmount);
258 | | }
259 | | }
260 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../data/Keys.sol";
8 | |
9 | | import "../market/MarketStoreUtils.sol";
10 | |
11 | | import "../deposit/DepositStoreUtils.sol";
12 | | import "../withdrawal/WithdrawalStoreUtils.sol";
13 | |
14 | | import "../position/Position.sol";
15 | | import "../position/PositionUtils.sol";
16 | | import "../position/PositionStoreUtils.sol";
17 | | import "../position/IncreasePositionUtils.sol";
18 | | import "../position/DecreasePositionUtils.sol";
19 | |
20 | | import "../order/OrderStoreUtils.sol";
21 | |
22 | | import "../market/MarketUtils.sol";
23 | | import "../market/Market.sol";
24 | | import "./ReaderPricingUtils.sol";
25 | |
26 | | // @title ReaderUtils
27 | | // @dev Library for read utils functions
28 | | // convers some internal library functions into internal functions to reduce
29 | | // the Reader contract size
30 | * | library ReaderUtils {
31 | | using SignedMath for int256;
32 | | using SafeCast for uint256;
33 | | using SafeCast for int256;
34 | | using Price for Price.Props;
35 | | using Position for Position.Props;
36 | | using Order for Order.Props;
37 | |
38 | | struct VirtualInventory {
39 | | uint256 virtualPoolAmountForLongToken;
40 | | uint256 virtualPoolAmountForShortToken;
41 | | int256 virtualInventoryForPositions;
42 | | }
43 | |
44 | | struct MarketInfo {
45 | | Market.Props market;
46 | | uint256 borrowingFactorPerSecondForLongs;
47 | | uint256 borrowingFactorPerSecondForShorts;
48 | | BaseFundingValues baseFunding;
49 | | MarketUtils.GetNextFundingAmountPerSizeResult nextFunding;
50 | | VirtualInventory virtualInventory;
51 | | bool isDisabled;
52 | | }
53 | |
54 | | struct PositionInfo {
55 | | Position.Props position;
56 | | PositionPricingUtils.PositionFees fees;
57 | | ReaderPricingUtils.ExecutionPriceResult executionPriceResult;
58 | | int256 basePnlUsd;
59 | | int256 uncappedBasePnlUsd;
60 | | int256 pnlAfterPriceImpactUsd;
61 | | }
62 | |
63 | | struct GetPositionInfoCache {
64 | | Market.Props market;
65 | | Price.Props collateralTokenPrice;
66 | | uint256 pendingBorrowingFeeUsd;
67 | | }
68 | |
69 | | struct BaseFundingValues {
70 | | MarketUtils.PositionType fundingFeeAmountPerSize;
71 | | MarketUtils.PositionType claimableFundingAmountPerSize;
72 | | }
73 | |
74 | * | function getNextBorrowingFees(
75 | | DataStore dataStore,
76 | | Position.Props memory position,
77 | | Market.Props memory market,
78 | | MarketUtils.MarketPrices memory prices
79 | * | ) internal view returns (uint256) {
80 | * | return MarketUtils.getNextBorrowingFees(
81 | * | dataStore,
82 | * | position,
83 | * | market,
84 | * | prices
85 | | );
86 | | }
87 | |
88 | * | function getBorrowingFees(
89 | | DataStore dataStore,
90 | | Price.Props memory collateralTokenPrice,
91 | | uint256 borrowingFeeUsd
92 | * | ) internal view returns (PositionPricingUtils.PositionBorrowingFees memory) {
93 | * | return PositionPricingUtils.getBorrowingFees(
94 | * | dataStore,
95 | * | collateralTokenPrice,
96 | * | borrowingFeeUsd
97 | | );
98 | | }
99 | |
100 | * | function getBaseFundingValues(DataStore dataStore, Market.Props memory market) internal view returns (BaseFundingValues memory) {
101 | * | BaseFundingValues memory values;
102 | |
103 | * | values.fundingFeeAmountPerSize.long.longToken = MarketUtils.getFundingFeeAmountPerSize(
104 | * | dataStore,
105 | * | market.marketToken,
106 | * | market.longToken,
107 | * | true // isLong
108 | | );
109 | |
110 | * | values.fundingFeeAmountPerSize.long.shortToken = MarketUtils.getFundingFeeAmountPerSize(
111 | * | dataStore,
112 | * | market.marketToken,
113 | * | market.shortToken,
114 | * | true // isLong
115 | | );
116 | |
117 | * | values.fundingFeeAmountPerSize.short.longToken = MarketUtils.getFundingFeeAmountPerSize(
118 | * | dataStore,
119 | * | market.marketToken,
120 | * | market.longToken,
121 | * | false // isLong
122 | | );
123 | |
124 | * | values.fundingFeeAmountPerSize.short.shortToken = MarketUtils.getFundingFeeAmountPerSize(
125 | * | dataStore,
126 | * | market.marketToken,
127 | * | market.shortToken,
128 | * | false // isLong
129 | | );
130 | |
131 | * | values.claimableFundingAmountPerSize.long.longToken = MarketUtils.getClaimableFundingAmountPerSize(
132 | * | dataStore,
133 | * | market.marketToken,
134 | * | market.longToken,
135 | * | true // isLong
136 | | );
137 | |
138 | * | values.claimableFundingAmountPerSize.long.shortToken = MarketUtils.getClaimableFundingAmountPerSize(
139 | * | dataStore,
140 | * | market.marketToken,
141 | * | market.shortToken,
142 | * | true // isLong
143 | | );
144 | |
145 | * | values.claimableFundingAmountPerSize.short.longToken = MarketUtils.getClaimableFundingAmountPerSize(
146 | * | dataStore,
147 | * | market.marketToken,
148 | * | market.longToken,
149 | * | false // isLong
150 | | );
151 | |
152 | * | values.claimableFundingAmountPerSize.short.shortToken = MarketUtils.getClaimableFundingAmountPerSize(
153 | * | dataStore,
154 | * | market.marketToken,
155 | * | market.shortToken,
156 | * | false // isLong
157 | | );
158 | |
159 | * | return values;
160 | | }
161 | |
162 | * | function getNextFundingAmountPerSize(
163 | | DataStore dataStore,
164 | | Market.Props memory market,
165 | | MarketUtils.MarketPrices memory prices
166 | * | ) internal view returns (MarketUtils.GetNextFundingAmountPerSizeResult memory) {
167 | * | return MarketUtils.getNextFundingAmountPerSize(
168 | * | dataStore,
169 | * | market,
170 | * | prices
171 | | );
172 | | }
173 | |
174 | * | function getMarketInfo(
175 | | DataStore dataStore,
176 | | MarketUtils.MarketPrices memory prices,
177 | | address marketKey
178 | * | ) internal view returns (MarketInfo memory) {
179 | * | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey);
180 | |
181 | * | uint256 borrowingFactorPerSecondForLongs = MarketUtils.getBorrowingFactorPerSecond(
182 | * | dataStore,
183 | * | market,
184 | * | prices,
185 | * | true
186 | | );
187 | |
188 | * | uint256 borrowingFactorPerSecondForShorts = MarketUtils.getBorrowingFactorPerSecond(
189 | * | dataStore,
190 | * | market,
191 | * | prices,
192 | * | false
193 | | );
194 | |
195 | * | BaseFundingValues memory baseFunding = getBaseFundingValues(dataStore, market);
196 | |
197 | * | MarketUtils.GetNextFundingAmountPerSizeResult memory nextFunding = getNextFundingAmountPerSize(
198 | * | dataStore,
199 | * | market,
200 | * | prices
201 | | );
202 | |
203 | * | VirtualInventory memory virtualInventory = getVirtualInventory(dataStore, market);
204 | |
205 | * | bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));
206 | |
207 | * | return
208 | * | MarketInfo(
209 | * | market,
210 | * | borrowingFactorPerSecondForLongs,
211 | * | borrowingFactorPerSecondForShorts,
212 | * | baseFunding,
213 | * | nextFunding,
214 | * | virtualInventory,
215 | * | isMarketDisabled
216 | | );
217 | | }
218 | |
219 | * | function getVirtualInventory(
220 | | DataStore dataStore,
221 | | Market.Props memory market
222 | * | ) internal view returns (VirtualInventory memory) {
223 | * | (, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils
224 | * | .getVirtualInventoryForSwaps(dataStore, market.marketToken);
225 | * | (, int256 virtualInventoryForPositions) = MarketUtils.getVirtualInventoryForPositions(
226 | * | dataStore,
227 | * | market.indexToken
228 | | );
229 | |
230 | * | return
231 | * | VirtualInventory(
232 | * | virtualPoolAmountForLongToken,
233 | * | virtualPoolAmountForShortToken,
234 | * | virtualInventoryForPositions
235 | | );
236 | | }
237 | |
238 | * | function getPositionInfo(
239 | | DataStore dataStore,
240 | | IReferralStorage referralStorage,
241 | | bytes32 positionKey,
242 | | MarketUtils.MarketPrices memory prices,
243 | | uint256 sizeDeltaUsd,
244 | | address uiFeeReceiver,
245 | | bool usePositionSizeAsSizeDeltaUsd
246 | * | ) internal view returns (PositionInfo memory) {
247 | * | PositionInfo memory positionInfo;
248 | * | GetPositionInfoCache memory cache;
249 | |
250 | * | positionInfo.position = PositionStoreUtils.get(dataStore, positionKey);
251 | * | cache.market = MarketStoreUtils.get(dataStore, positionInfo.position.market());
252 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(positionInfo.position.collateralToken(), cache.market, prices);
253 | |
254 | * | if (usePositionSizeAsSizeDeltaUsd) {
255 | * | sizeDeltaUsd = positionInfo.position.sizeInUsd();
256 | | }
257 | |
258 | * | positionInfo.executionPriceResult = ReaderPricingUtils.getExecutionPrice(
259 | * | dataStore,
260 | * | cache.market,
261 | * | prices.indexTokenPrice,
262 | * | positionInfo.position.sizeInUsd(),
263 | * | positionInfo.position.sizeInTokens(),
264 | * | -sizeDeltaUsd.toInt256(),
265 | * | positionInfo.position.isLong()
266 | | );
267 | |
268 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(
269 | * | dataStore, // dataStore
270 | * | referralStorage, // referralStorage
271 | * | positionInfo.position, // position
272 | * | cache.collateralTokenPrice, // collateralTokenPrice
273 | * | positionInfo.executionPriceResult.priceImpactUsd > 0, // forPositiveImpact
274 | * | cache.market.longToken, // longToken
275 | * | cache.market.shortToken, // shortToken
276 | * | sizeDeltaUsd, // sizeDeltaUsd
277 | * | uiFeeReceiver // uiFeeReceiver
278 | | );
279 | |
280 | * | positionInfo.fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);
281 | |
282 | | // borrowing and funding fees need to be overwritten with pending values otherwise they
283 | | // would be using storage values that have not yet been updated
284 | * | cache.pendingBorrowingFeeUsd = getNextBorrowingFees(dataStore, positionInfo.position, cache.market, prices);
285 | |
286 | * | positionInfo.fees.borrowing = getBorrowingFees(
287 | * | dataStore,
288 | * | cache.collateralTokenPrice,
289 | * | cache.pendingBorrowingFeeUsd
290 | | );
291 | |
292 | * | MarketUtils.GetNextFundingAmountPerSizeResult memory nextFundingAmountResult = getNextFundingAmountPerSize(dataStore, cache.market, prices);
293 | |
294 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(
295 | * | dataStore,
296 | * | positionInfo.position.market(),
297 | * | positionInfo.position.collateralToken(),
298 | * | positionInfo.position.isLong()
299 | | );
300 | |
301 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
302 | * | dataStore,
303 | * | positionInfo.position.market(),
304 | * | cache.market.longToken,
305 | * | positionInfo.position.isLong()
306 | | );
307 | |
308 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
309 | * | dataStore,
310 | * | positionInfo.position.market(),
311 | * | cache.market.shortToken,
312 | * | positionInfo.position.isLong()
313 | | );
314 | |
315 | | // see MarketUtils.getNextFundingAmountPerSize for more info on why this multiplier is needed
316 | | // a short summary:
317 | | // - funding values are split based on long and short token
318 | | // - for single token markets, these tokens are the same
319 | | // - so when the funding values are applied in updateFundingState, they are applied twice
320 | | // - e.g.
321 | | // - increase fundingFeeAmountPerSize(market, collateralToken: token0, isLong: true) by 10
322 | | // - increase fundingFeeAmountPerSize(market, collateralToken: token1, isLong: true) by 10
323 | | // - for a single token market, token0 is the same as token1, so the value would be increased by 20
324 | | // - to avoid costs being doubled, these values are halved in MarketUtils.getNextFundingAmountPerSize
325 | | // - the reader code needs to double the values, because in the code below the nextFundingAmountResult
326 | | // values are applied virtually instead of the DataStore values being updated
327 | * | uint256 multiplier = cache.market.longToken == cache.market.shortToken ? 2 : 1;
328 | |
329 | * | if (positionInfo.position.isLong()) {
330 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.longToken * multiplier;
331 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.shortToken * multiplier;
332 | |
333 | * | if (positionInfo.position.collateralToken() == cache.market.longToken) {
334 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.longToken * multiplier;
335 | | } else {
336 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.shortToken * multiplier;
337 | | }
338 | | } else {
339 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.longToken * multiplier;
340 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.shortToken * multiplier;
341 | |
342 | * | if (positionInfo.position.collateralToken() == cache.market.longToken) {
343 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.longToken * multiplier;
344 | | } else {
345 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.shortToken * multiplier;
346 | | }
347 | | }
348 | |
349 | * | positionInfo.fees.funding = PositionPricingUtils.getFundingFees(
350 | * | positionInfo.fees.funding,
351 | * | positionInfo.position
352 | | );
353 | |
354 | * | (positionInfo.basePnlUsd, positionInfo.uncappedBasePnlUsd, /* sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd(
355 | * | dataStore,
356 | * | cache.market,
357 | * | prices,
358 | * | positionInfo.position,
359 | * | sizeDeltaUsd
360 | | );
361 | |
362 | * | positionInfo.pnlAfterPriceImpactUsd = positionInfo.executionPriceResult.priceImpactUsd + positionInfo.basePnlUsd;
363 | |
364 | * | positionInfo.fees.totalCostAmountExcludingFunding =
365 | * | positionInfo.fees.positionFeeAmount
366 | * | + positionInfo.fees.borrowing.borrowingFeeAmount
367 | * | + positionInfo.fees.ui.uiFeeAmount
368 | * | - positionInfo.fees.referral.traderDiscountAmount;
369 | |
370 | * | positionInfo.fees.totalCostAmount =
371 | * | positionInfo.fees.totalCostAmountExcludingFunding
372 | * | + positionInfo.fees.funding.fundingFeeAmount;
373 | |
374 | * | return positionInfo;
375 | | }
376 | | }
377 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderWithdrawalUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | |
7 | | import "../data/Keys.sol";
8 | |
9 | | import "../market/MarketStoreUtils.sol";
10 | |
11 | | import "../deposit/DepositStoreUtils.sol";
12 | | import "../withdrawal/WithdrawalStoreUtils.sol";
13 | |
14 | | import "../position/Position.sol";
15 | | import "../position/PositionUtils.sol";
16 | | import "../position/PositionStoreUtils.sol";
17 | | import "../position/IncreasePositionUtils.sol";
18 | | import "../position/DecreasePositionUtils.sol";
19 | |
20 | | import "../order/OrderStoreUtils.sol";
21 | |
22 | | import "../market/MarketUtils.sol";
23 | | import "../market/Market.sol";
24 | | import "./ReaderPricingUtils.sol";
25 | |
26 | * | library ReaderWithdrawalUtils {
27 | | using SignedMath for int256;
28 | | using SafeCast for uint256;
29 | | using SafeCast for int256;
30 | | using Price for Price.Props;
31 | | using Position for Position.Props;
32 | | using Order for Order.Props;
33 | |
34 | | struct GetWithdrawalAmountOutCache {
35 | | uint256 poolValue;
36 | | uint256 marketTokensSupply;
37 | |
38 | | uint256 longTokenPoolAmount;
39 | | uint256 shortTokenPoolAmount;
40 | |
41 | | uint256 longTokenPoolUsd;
42 | | uint256 shortTokenPoolUsd;
43 | |
44 | | uint256 totalPoolUsd;
45 | |
46 | | uint256 marketTokensUsd;
47 | |
48 | | uint256 longTokenOutputUsd;
49 | | uint256 shortTokenOutputUsd;
50 | |
51 | | uint256 longTokenOutputAmount;
52 | | uint256 shortTokenOutputAmount;
53 | | }
54 | |
55 | * | function getWithdrawalAmountOut(
56 | | DataStore dataStore,
57 | | Market.Props memory market,
58 | | MarketUtils.MarketPrices memory prices,
59 | | uint256 marketTokenAmount,
60 | | address uiFeeReceiver,
61 | | ISwapPricingUtils.SwapPricingType swapPricingType
62 | * | ) internal view returns (uint256, uint256) {
63 | * | GetWithdrawalAmountOutCache memory cache;
64 | |
65 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
66 | * | dataStore,
67 | * | market,
68 | * | prices.indexTokenPrice,
69 | * | prices.longTokenPrice,
70 | * | prices.shortTokenPrice,
71 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
72 | * | false
73 | | );
74 | |
75 | * | if (poolValueInfo.poolValue <= 0) {
76 | | revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);
77 | | }
78 | |
79 | * | cache.poolValue = poolValueInfo.poolValue.toUint256();
80 | * | cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
81 | |
82 | * | cache.longTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.longToken);
83 | * | cache.shortTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.shortToken);
84 | |
85 | * | cache.longTokenPoolUsd = cache.longTokenPoolAmount * prices.longTokenPrice.max;
86 | * | cache.shortTokenPoolUsd = cache.shortTokenPoolAmount * prices.shortTokenPrice.max;
87 | |
88 | * | cache.totalPoolUsd = cache.longTokenPoolUsd + cache.shortTokenPoolUsd;
89 | |
90 | * | cache.marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, cache.poolValue, cache.marketTokensSupply);
91 | |
92 | * | cache.longTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.longTokenPoolUsd, cache.totalPoolUsd);
93 | * | cache.shortTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.shortTokenPoolUsd, cache.totalPoolUsd);
94 | |
95 | * | cache.longTokenOutputAmount = cache.longTokenOutputUsd / prices.longTokenPrice.max;
96 | * | cache.shortTokenOutputAmount = cache.shortTokenOutputUsd / prices.shortTokenPrice.max;
97 | |
98 | * | SwapPricingUtils.SwapFees memory longTokenFees = SwapPricingUtils.getSwapFees(
99 | * | dataStore,
100 | * | market.marketToken,
101 | * | cache.longTokenOutputAmount,
102 | * | false, // forPositiveImpact
103 | * | uiFeeReceiver,
104 | * | swapPricingType
105 | | );
106 | |
107 | * | SwapPricingUtils.SwapFees memory shortTokenFees = SwapPricingUtils.getSwapFees(
108 | * | dataStore,
109 | * | market.marketToken,
110 | * | cache.shortTokenOutputAmount,
111 | * | false, // forPositiveImpact
112 | * | uiFeeReceiver,
113 | * | swapPricingType
114 | | );
115 | |
116 | * | return (
117 | * | longTokenFees.amountAfterFees,
118 | * | shortTokenFees.amountAfterFees
119 | | );
120 | | }
121 | | }
122 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/IReferralStorage.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./ReferralTier.sol";
6 | |
7 | | // @title IReferralStorage
8 | | // @dev Interface for ReferralStorage
9 | | interface IReferralStorage {
10 | | // @dev get the owner of a referral code
11 | | // @param _code the referral code
12 | | // @return the owner of the referral code
13 | | function codeOwners(bytes32 _code) external view returns (address);
14 | | // @dev get the referral code of a trader
15 | | // @param _account the address of the trader
16 | | // @return the referral code
17 | | function traderReferralCodes(address _account) external view returns (bytes32);
18 | | // @dev get the trader discount share for an affiliate
19 | | // @param _account the address of the affiliate
20 | | // @return the trader discount share
21 | | function referrerDiscountShares(address _account) external view returns (uint256);
22 | | // @dev get the tier level of an affiliate
23 | | // @param _account the address of the affiliate
24 | | // @return the tier level of the affiliate
25 | | function referrerTiers(address _account) external view returns (uint256);
26 | | // @dev get the referral info for a trader
27 | | // @param _account the address of the trader
28 | | // @return (referral code, affiliate)
29 | | function getTraderReferralInfo(address _account) external view returns (bytes32, address);
30 | | // @dev set the referral code for a trader
31 | | // @param _account the address of the trader
32 | | // @param _code the referral code
33 | | function setTraderReferralCode(address _account, bytes32 _code) external;
34 | | // @dev set the values for a tier
35 | | // @param _tierId the tier level
36 | | // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount)
37 | | // @param _discountShare the share of the totalRebate for traders
38 | | function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;
39 | | // @dev set the tier for an affiliate
40 | | // @param _tierId the tier level
41 | | function setReferrerTier(address _referrer, uint256 _tierId) external;
42 | | // @dev set the owner for a referral code
43 | | // @param _code the referral code
44 | | // @param _newAccount the new owner
45 | | function govSetCodeOwner(bytes32 _code, address _newAccount) external;
46 | |
47 | | // @dev get the tier values for a tier level
48 | | // @param _tierLevel the tier level
49 | | // @return (totalRebate, discountShare)
50 | | function tiers(uint256 _tierLevel) external view returns (uint256, uint256);
51 | | }
52 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | * | library ReferralEventUtils {
10 | | using EventUtils for EventUtils.AddressItems;
11 | | using EventUtils for EventUtils.UintItems;
12 | | using EventUtils for EventUtils.IntItems;
13 | | using EventUtils for EventUtils.BoolItems;
14 | | using EventUtils for EventUtils.Bytes32Items;
15 | | using EventUtils for EventUtils.BytesItems;
16 | | using EventUtils for EventUtils.StringItems;
17 | |
18 | | function emitAffiliateRewardUpdated(
19 | | EventEmitter eventEmitter,
20 | | address market,
21 | | address token,
22 | | address affiliate,
23 | | uint256 delta,
24 | | uint256 nextValue,
25 | | uint256 nextPoolValue
26 | | ) internal {
27 | | EventUtils.EventLogData memory eventData;
28 | |
29 | | eventData.addressItems.initItems(3);
30 | | eventData.addressItems.setItem(0, "market", market);
31 | | eventData.addressItems.setItem(1, "token", token);
32 | | eventData.addressItems.setItem(2, "affiliate", affiliate);
33 | |
34 | | eventData.uintItems.initItems(3);
35 | | eventData.uintItems.setItem(0, "delta", delta);
36 | | eventData.uintItems.setItem(1, "nextValue", nextValue);
37 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
38 | |
39 | | eventEmitter.emitEventLog2(
40 | | "AffiliateRewardUpdated",
41 | | Cast.toBytes32(market),
42 | | Cast.toBytes32(affiliate),
43 | | eventData
44 | | );
45 | | }
46 | |
47 | | function emitAffiliateRewardClaimed(
48 | | EventEmitter eventEmitter,
49 | | address market,
50 | | address token,
51 | | address affiliate,
52 | | address receiver,
53 | | uint256 amount,
54 | | uint256 nextPoolValue
55 | | ) internal {
56 | | EventUtils.EventLogData memory eventData;
57 | |
58 | | eventData.addressItems.initItems(4);
59 | | eventData.addressItems.setItem(0, "market", market);
60 | | eventData.addressItems.setItem(1, "token", token);
61 | | eventData.addressItems.setItem(2, "affiliate", affiliate);
62 | | eventData.addressItems.setItem(3, "receiver", receiver);
63 | |
64 | | eventData.uintItems.initItems(2);
65 | | eventData.uintItems.setItem(0, "amount", amount);
66 | | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
67 | |
68 | | eventEmitter.emitEventLog1(
69 | | "AffiliateRewardClaimed",
70 | | Cast.toBytes32(affiliate),
71 | | eventData
72 | | );
73 | | }
74 | | }
75 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralTier.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // @title ReferralTier
6 | | // @dev Struct for referral tiers
7 | * | library ReferralTier {
8 | | // @param totalRebate the total rebate for the tier (affiliate reward + trader discount)
9 | | // @param discountShare the share of the totalRebate for traders
10 | | struct Props {
11 | | uint256 totalRebate;
12 | | uint256 discountShare;
13 | | }
14 | | }
15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../data/Keys.sol";
7 | |
8 | | import "../event/EventEmitter.sol";
9 | | import "../market/MarketToken.sol";
10 | | import "../market/MarketUtils.sol";
11 | |
12 | | import "./IReferralStorage.sol";
13 | | import "./ReferralTier.sol";
14 | | import "./ReferralEventUtils.sol";
15 | |
16 | | import "../utils/Precision.sol";
17 | |
18 | | // @title ReferralUtils
19 | | // @dev Library for referral functions
20 | * | library ReferralUtils {
21 | | // @dev set the referral code for a trader
22 | | // @param referralStorage The referral storage instance to use.
23 | | // @param account The account of the trader.
24 | | // @param referralCode The referral code.
25 | * | function setTraderReferralCode(
26 | | IReferralStorage referralStorage,
27 | | address account,
28 | | bytes32 referralCode
29 | | ) internal {
30 | * | if (referralCode == bytes32(0)) { return; }
31 | |
32 | | // skip setting of the referral code if the user already has a referral code
33 | | if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }
34 | |
35 | | referralStorage.setTraderReferralCode(account, referralCode);
36 | | }
37 | |
38 | | // @dev Increments the affiliate's reward balance by the specified delta.
39 | | // @param dataStore The data store instance to use.
40 | | // @param eventEmitter The event emitter instance to use.
41 | | // @param market The market address.
42 | | // @param token The token address.
43 | | // @param affiliate The affiliate's address.
44 | | // @param trader The trader's address.
45 | | // @param delta The amount to increment the reward balance by.
46 | * | function incrementAffiliateReward(
47 | | DataStore dataStore,
48 | | EventEmitter eventEmitter,
49 | | address market,
50 | | address token,
51 | | address affiliate,
52 | | uint256 delta
53 | | ) internal {
54 | * | if (delta == 0) { return; }
55 | |
56 | | uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);
57 | | uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);
58 | |
59 | | ReferralEventUtils.emitAffiliateRewardUpdated(
60 | | eventEmitter,
61 | | market,
62 | | token,
63 | | affiliate,
64 | | delta,
65 | | nextValue,
66 | | nextPoolValue
67 | | );
68 | | }
69 | |
70 | | // @dev Gets the referral information for the specified trader.
71 | | // @param referralStorage The referral storage instance to use.
72 | | // @param trader The trader's address.
73 | | // @return The affiliate's address, the total rebate, and the discount share.
74 | * | function getReferralInfo(
75 | | IReferralStorage referralStorage,
76 | | address trader
77 | * | ) internal view returns (bytes32, address, uint256, uint256) {
78 | * | bytes32 code = referralStorage.traderReferralCodes(trader);
79 | * | address affiliate;
80 | * | uint256 totalRebate;
81 | * | uint256 discountShare;
82 | |
83 | * | if (code != bytes32(0)) {
84 | | affiliate = referralStorage.codeOwners(code);
85 | | uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);
86 | | (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);
87 | |
88 | | uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);
89 | | if (customDiscountShare != 0) {
90 | | discountShare = customDiscountShare;
91 | | }
92 | | }
93 | |
94 | * | return (
95 | * | code,
96 | * | affiliate,
97 | * | Precision.basisPointsToFloat(totalRebate),
98 | * | Precision.basisPointsToFloat(discountShare)
99 | | );
100 | | }
101 | |
102 | | // @dev Claims the affiliate's reward balance and transfers it to the specified receiver.
103 | | // @param dataStore The data store instance to use.
104 | | // @param eventEmitter The event emitter instance to use.
105 | | // @param market The market address.
106 | | // @param token The token address.
107 | | // @param account The affiliate's address.
108 | | // @param receiver The address to receive the reward.
109 | | function claimAffiliateReward(
110 | | DataStore dataStore,
111 | | EventEmitter eventEmitter,
112 | | address market,
113 | | address token,
114 | | address account,
115 | | address receiver
116 | | ) internal returns (uint256) {
117 | | bytes32 key = Keys.affiliateRewardKey(market, token, account);
118 | |
119 | | uint256 rewardAmount = dataStore.getUint(key);
120 | | dataStore.setUint(key, 0);
121 | |
122 | | uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);
123 | |
124 | | MarketToken(payable(market)).transferOut(
125 | | token,
126 | | receiver,
127 | | rewardAmount
128 | | );
129 | |
130 | | MarketUtils.validateMarketTokenBalance(dataStore, market);
131 | |
132 | | ReferralEventUtils.emitAffiliateRewardClaimed(
133 | | eventEmitter,
134 | | market,
135 | | token,
136 | | account,
137 | | receiver,
138 | | rewardAmount,
139 | | nextPoolValue
140 | | );
141 | |
142 | | return rewardAmount;
143 | | }
144 | | }
145 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/Role.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @title Role
7 | | * @dev Library for role keys
8 | | */
9 | * | library Role {
10 | | /**
11 | | * @dev The ROLE_ADMIN role.
12 | | * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9
13 | | */
14 | | bytes32 internal constant ROLE_ADMIN = keccak256(abi.encode("ROLE_ADMIN"));
15 | |
16 | | /**
17 | | * @dev The TIMELOCK_ADMIN role.
18 | | * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c
19 | | */
20 | | bytes32 internal constant TIMELOCK_ADMIN = keccak256(abi.encode("TIMELOCK_ADMIN"));
21 | |
22 | | /**
23 | | * @dev The TIMELOCK_MULTISIG role.
24 | | * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a
25 | | */
26 | | bytes32 internal constant TIMELOCK_MULTISIG = keccak256(abi.encode("TIMELOCK_MULTISIG"));
27 | |
28 | | /**
29 | | * @dev The CONFIG_KEEPER role.
30 | | * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b
31 | | */
32 | | bytes32 internal constant CONFIG_KEEPER = keccak256(abi.encode("CONFIG_KEEPER"));
33 | |
34 | | /**
35 | | * @dev The LIMITED_CONFIG_KEEPER role.
36 | | * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7
37 | | */
38 | | bytes32 internal constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode("LIMITED_CONFIG_KEEPER"));
39 | |
40 | | /**
41 | | * @dev The CONTROLLER role.
42 | | * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b
43 | | */
44 | * | bytes32 internal constant CONTROLLER = keccak256(abi.encode("CONTROLLER"));
45 | |
46 | | /**
47 | | * @dev The GOV_TOKEN_CONTROLLER role.
48 | | * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690
49 | | */
50 | | bytes32 internal constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode("GOV_TOKEN_CONTROLLER"));
51 | |
52 | | /**
53 | | * @dev The ROUTER_PLUGIN role.
54 | | * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3
55 | | */
56 | * | bytes32 internal constant ROUTER_PLUGIN = keccak256(abi.encode("ROUTER_PLUGIN"));
57 | |
58 | | /**
59 | | * @dev The MARKET_KEEPER role.
60 | | * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae
61 | | */
62 | | bytes32 internal constant MARKET_KEEPER = keccak256(abi.encode("MARKET_KEEPER"));
63 | |
64 | | /**
65 | | * @dev The FEE_KEEPER role.
66 | | * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8
67 | | */
68 | | bytes32 internal constant FEE_KEEPER = keccak256(abi.encode("FEE_KEEPER"));
69 | |
70 | | /**
71 | | * @dev The FEE_DISTRIBUTION_KEEPER role.
72 | | * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2
73 | | */
74 | | bytes32 internal constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode("FEE_DISTRIBUTION_KEEPER"));
75 | |
76 | | /**
77 | | * @dev The ORDER_KEEPER role.
78 | | * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794
79 | | */
80 | * | bytes32 internal constant ORDER_KEEPER = keccak256(abi.encode("ORDER_KEEPER"));
81 | |
82 | | /**
83 | | * @dev The FROZEN_ORDER_KEEPER role.
84 | | * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07
85 | | */
86 | * | bytes32 internal constant FROZEN_ORDER_KEEPER = keccak256(abi.encode("FROZEN_ORDER_KEEPER"));
87 | |
88 | | /**
89 | | * @dev The PRICING_KEEPER role.
90 | | * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103
91 | | */
92 | | bytes32 internal constant PRICING_KEEPER = keccak256(abi.encode("PRICING_KEEPER"));
93 | | /**
94 | | * @dev The LIQUIDATION_KEEPER role.
95 | | * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e
96 | | */
97 | * | bytes32 internal constant LIQUIDATION_KEEPER = keccak256(abi.encode("LIQUIDATION_KEEPER"));
98 | | /**
99 | | * @dev The ADL_KEEPER role.
100 | | * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91
101 | | */
102 | * | bytes32 internal constant ADL_KEEPER = keccak256(abi.encode("ADL_KEEPER"));
103 | | }
104 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/RoleModule.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./RoleStore.sol";
6 | |
7 | | /**
8 | | * @title RoleModule
9 | | * @dev Contract for role validation functions
10 | | */
11 | | contract RoleModule {
12 | | RoleStore public immutable roleStore;
13 | |
14 | | /**
15 | | * @dev Constructor that initializes the role store for this contract.
16 | | *
17 | | * @param _roleStore The contract instance to use as the role store.
18 | | */
19 | | constructor(RoleStore _roleStore) {
20 | | roleStore = _roleStore;
21 | | }
22 | |
23 | | /**
24 | | * @dev Only allows the contract's own address to call the function.
25 | | */
26 | | modifier onlySelf() {
27 | * | if (msg.sender != address(this)) {
28 | | revert Errors.Unauthorized(msg.sender, "SELF");
29 | | }
30 | | _;
31 | | }
32 | |
33 | | /**
34 | | * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function.
35 | | */
36 | | modifier onlyTimelockMultisig() {
37 | | _validateRole(Role.TIMELOCK_MULTISIG, "TIMELOCK_MULTISIG");
38 | | _;
39 | | }
40 | |
41 | | /**
42 | | * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function.
43 | | */
44 | | modifier onlyTimelockAdmin() {
45 | | _validateRole(Role.TIMELOCK_ADMIN, "TIMELOCK_ADMIN");
46 | | _;
47 | | }
48 | |
49 | | /**
50 | | * @dev Only allows addresses with the CONFIG_KEEPER role to call the function.
51 | | */
52 | | modifier onlyConfigKeeper() {
53 | | _validateRole(Role.CONFIG_KEEPER, "CONFIG_KEEPER");
54 | | _;
55 | | }
56 | |
57 | | /**
58 | | * @dev Only allows addresses with the CONTROLLER role to call the function.
59 | | */
60 | | modifier onlyController() {
61 | * | _validateRole(Role.CONTROLLER, "CONTROLLER");
62 | * | _;
63 | | }
64 | |
65 | | /**
66 | | * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function.
67 | | */
68 | | modifier onlyGovTokenController() {
69 | | _validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER");
70 | | _;
71 | | }
72 | |
73 | | /**
74 | | * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function.
75 | | */
76 | | modifier onlyRouterPlugin() {
77 | * | _validateRole(Role.ROUTER_PLUGIN, "ROUTER_PLUGIN");
78 | | _;
79 | | }
80 | |
81 | | /**
82 | | * @dev Only allows addresses with the MARKET_KEEPER role to call the function.
83 | | */
84 | | modifier onlyMarketKeeper() {
85 | | _validateRole(Role.MARKET_KEEPER, "MARKET_KEEPER");
86 | | _;
87 | | }
88 | |
89 | | /**
90 | | * @dev Only allows addresses with the FEE_KEEPER role to call the function.
91 | | */
92 | | modifier onlyFeeKeeper() {
93 | | _validateRole(Role.FEE_KEEPER, "FEE_KEEPER");
94 | | _;
95 | | }
96 | |
97 | | /**
98 | | * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function.
99 | | */
100 | | modifier onlyFeeDistributionKeeper() {
101 | | _validateRole(Role.FEE_DISTRIBUTION_KEEPER, "FEE_DISTRIBUTION_KEEPER");
102 | | _;
103 | | }
104 | |
105 | | /**
106 | | * @dev Only allows addresses with the ORDER_KEEPER role to call the function.
107 | | */
108 | | modifier onlyOrderKeeper() {
109 | * | _validateRole(Role.ORDER_KEEPER, "ORDER_KEEPER");
110 | * | _;
111 | | }
112 | |
113 | | /**
114 | | * @dev Only allows addresses with the PRICING_KEEPER role to call the function.
115 | | */
116 | | modifier onlyPricingKeeper() {
117 | | _validateRole(Role.PRICING_KEEPER, "PRICING_KEEPER");
118 | | _;
119 | | }
120 | |
121 | | /**
122 | | * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function.
123 | | */
124 | | modifier onlyLiquidationKeeper() {
125 | * | _validateRole(Role.LIQUIDATION_KEEPER, "LIQUIDATION_KEEPER");
126 | * | _;
127 | | }
128 | |
129 | | /**
130 | | * @dev Only allows addresses with the ADL_KEEPER role to call the function.
131 | | */
132 | | modifier onlyAdlKeeper() {
133 | * | _validateRole(Role.ADL_KEEPER, "ADL_KEEPER");
134 | * | _;
135 | | }
136 | |
137 | | /**
138 | | * @dev Validates that the caller has the specified role.
139 | | *
140 | | * If the caller does not have the specified role, the transaction is reverted.
141 | | *
142 | | * @param role The key of the role to validate.
143 | | * @param roleName The name of the role to validate.
144 | | */
145 | * | function _validateRole(bytes32 role, string memory roleName) internal view {
146 | * | if (!roleStore.hasRole(msg.sender, role)) {
147 | | revert Errors.Unauthorized(msg.sender, roleName);
148 | | }
149 | | }
150 | | }
151 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/RoleStore.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6 | | import "../utils/EnumerableValues.sol";
7 | | import "./Role.sol";
8 | | import "../error/Errors.sol";
9 | |
10 | | /**
11 | | * @title RoleStore
12 | | * @dev Stores roles and their members.
13 | | */
14 | * | contract RoleStore {
15 | | using EnumerableSet for EnumerableSet.AddressSet;
16 | | using EnumerableSet for EnumerableSet.Bytes32Set;
17 | | using EnumerableValues for EnumerableSet.AddressSet;
18 | | using EnumerableValues for EnumerableSet.Bytes32Set;
19 | |
20 | | EnumerableSet.Bytes32Set internal roles;
21 | | mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;
22 | | // checking if an account has a role is a frequently used function
23 | | // roleCache helps to save gas by offering a more efficient lookup
24 | | // vs calling roleMembers[key].contains(account)
25 | | mapping(address => mapping (bytes32 => bool)) roleCache;
26 | |
27 | | modifier onlyRoleAdmin() {
28 | | if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {
29 | | revert Errors.Unauthorized(msg.sender, "ROLE_ADMIN");
30 | | }
31 | | _;
32 | | }
33 | |
34 | | constructor() {
35 | | _grantRole(msg.sender, Role.ROLE_ADMIN);
36 | | }
37 | |
38 | | /**
39 | | * @dev Grants the specified role to the given account.
40 | | *
41 | | * @param account The address of the account.
42 | | * @param roleKey The key of the role to grant.
43 | | */
44 | | function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {
45 | | _grantRole(account, roleKey);
46 | | }
47 | |
48 | | /**
49 | | * @dev Revokes the specified role from the given account.
50 | | *
51 | | * @param account The address of the account.
52 | | * @param roleKey The key of the role to revoke.
53 | | */
54 | | function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {
55 | | _revokeRole(account, roleKey);
56 | | }
57 | |
58 | | /**
59 | | * @dev Returns true if the given account has the specified role.
60 | | *
61 | | * @param account The address of the account.
62 | | * @param roleKey The key of the role.
63 | | * @return True if the account has the role, false otherwise.
64 | | */
65 | * | function hasRole(address account, bytes32 roleKey) public view returns (bool) {
66 | * | return roleCache[account][roleKey];
67 | | }
68 | |
69 | | /**
70 | | * @dev Returns the number of roles stored in the contract.
71 | | *
72 | | * @return The number of roles.
73 | | */
74 | | function getRoleCount() external view returns (uint256) {
75 | | return roles.length();
76 | | }
77 | |
78 | | /**
79 | | * @dev Returns the keys of the roles stored in the contract.
80 | | *
81 | | * @param start The starting index of the range of roles to return.
82 | | * @param end The ending index of the range of roles to return.
83 | | * @return The keys of the roles.
84 | | */
85 | | function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {
86 | | return roles.valuesAt(start, end);
87 | | }
88 | |
89 | | /**
90 | | * @dev Returns the number of members of the specified role.
91 | | *
92 | | * @param roleKey The key of the role.
93 | | * @return The number of members of the role.
94 | | */
95 | | function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {
96 | | return roleMembers[roleKey].length();
97 | | }
98 | |
99 | | /**
100 | | * @dev Returns the members of the specified role.
101 | | *
102 | | * @param roleKey The key of the role.
103 | | * @param start the start index, the value for this index will be included.
104 | | * @param end the end index, the value for this index will not be included.
105 | | * @return The members of the role.
106 | | */
107 | | function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {
108 | | return roleMembers[roleKey].valuesAt(start, end);
109 | | }
110 | |
111 | | function _grantRole(address account, bytes32 roleKey) internal {
112 | | roles.add(roleKey);
113 | | roleMembers[roleKey].add(account);
114 | | roleCache[account][roleKey] = true;
115 | | }
116 | |
117 | | function _revokeRole(address account, bytes32 roleKey) internal {
118 | | roleMembers[roleKey].remove(account);
119 | | roleCache[account][roleKey] = false;
120 | |
121 | | if (roleMembers[roleKey].length() == 0) {
122 | | if (roleKey == Role.ROLE_ADMIN) {
123 | | revert Errors.ThereMustBeAtLeastOneRoleAdmin();
124 | | }
125 | | if (roleKey == Role.TIMELOCK_MULTISIG) {
126 | | revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();
127 | | }
128 | | }
129 | | }
130 | | }
131 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/BaseRouter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
8 | |
9 | | import "../utils/PayableMulticall.sol";
10 | | import "../utils/AccountUtils.sol";
11 | |
12 | | import "../data/DataStore.sol";
13 | | import "../event/EventEmitter.sol";
14 | | import "../token/TokenUtils.sol";
15 | |
16 | | import "./Router.sol";
17 | |
18 | | contract BaseRouter is ReentrancyGuard, PayableMulticall, RoleModule {
19 | | using SafeERC20 for IERC20;
20 | | event BaseRouterDeployed(address deployedTo);
21 | |
22 | | Router public immutable router;
23 | | DataStore public immutable dataStore;
24 | | EventEmitter public immutable eventEmitter;
25 | |
26 | | constructor(
27 | | Router _router,
28 | | RoleStore _roleStore,
29 | | DataStore _dataStore,
30 | | EventEmitter _eventEmitter
31 | | ) RoleModule(_roleStore) {
32 | | router = _router;
33 | | dataStore = _dataStore;
34 | | eventEmitter = _eventEmitter;
35 | |
36 | | emit BaseRouterDeployed(address(this));
37 | | }
38 | |
39 | | // @dev Wraps the specified amount of native tokens into WNT then sends the WNT to the specified address
40 | * | function sendWnt(
41 | | address receiver,
42 | | uint256 amount
43 | | ) external payable nonReentrant {
44 | * | AccountUtils.validateReceiver(receiver);
45 | * | TokenUtils.depositAndSendWrappedNativeToken(
46 | * | dataStore,
47 | * | receiver,
48 | * | amount
49 | | );
50 | | }
51 | |
52 | | // @dev Sends the given amount of tokens to the given address
53 | * | function sendTokens(
54 | | address token,
55 | | address receiver,
56 | | uint256 amount
57 | * | ) external payable nonReentrant {
58 | * | AccountUtils.validateReceiver(receiver);
59 | * | address account = msg.sender;
60 | * | router.pluginTransfer(token, account, receiver, amount);
61 | | }
62 | |
63 | | function sendNativeToken(
64 | | address receiver,
65 | | uint256 amount
66 | | ) external payable nonReentrant {
67 | | AccountUtils.validateReceiver(receiver);
68 | | TokenUtils.sendNativeToken(dataStore, receiver, amount);
69 | | }
70 | | }
71 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/ExchangeRouter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../exchange/IDepositHandler.sol";
6 | | import "../exchange/IWithdrawalHandler.sol";
7 | | import "../exchange/IShiftHandler.sol";
8 | | import "../exchange/IOrderHandler.sol";
9 | | import "../external/IExternalHandler.sol";
10 | |
11 | | import "../feature/FeatureUtils.sol";
12 | |
13 | | import "./BaseRouter.sol";
14 | | import "./IExchangeRouter.sol";
15 | |
16 | | /**
17 | | * @title ExchangeRouter
18 | | * @dev Router for exchange functions, supports functions which require
19 | | * token transfers from the user
20 | | *
21 | | * IMPORTANT: PayableMulticall uses delegatecall, msg.value will be the same for each delegatecall
22 | | * extra care should be taken when using msg.value in any of the functions in this contract
23 | | *
24 | | * To avoid front-running issues, most actions require two steps to execute:
25 | | *
26 | | * - User sends transaction with request details, e.g. deposit / withdraw liquidity,
27 | | * swap, increase / decrease position
28 | | * - Keepers listen for the transactions, include the prices for the request then
29 | | * send a transaction to execute the request
30 | | *
31 | | * Prices are provided by an off-chain oracle system:
32 | | *
33 | | * - Oracle keepers continually check the latest blocks
34 | | * - When there is a new block, oracle keepers fetch the latest prices from
35 | | * reference exchanges
36 | | * - Oracle keepers then sign the median price for each token together with
37 | | * the block hash
38 | | * - Oracle keepers then send the data and signature to archive nodes
39 | | * - Archive nodes display this information for anyone to query
40 | | *
41 | | * Example:
42 | | *
43 | | * - Block 100 is finalized on the blockchain
44 | | * - Oracle keepers observe this block
45 | | * - Oracle keepers pull the latest prices from reference exchanges,
46 | | * token A: price 20,000, token B: price 80,000
47 | | * - Oracle keepers sign [chainId, blockhash(100), 20,000], [chainId, blockhash(100), 80,000]
48 | | * - If in block 100, there was a market order to open a long position for token A,
49 | | * the market order would have a block number of 100
50 | | * - The prices signed at block 100 can be used to execute this order
51 | | * - Order keepers would bundle the signature and price data for token A
52 | | * then execute the order
53 | | */
54 | * | contract ExchangeRouter is IExchangeRouter, BaseRouter {
55 | | using Deposit for Deposit.Props;
56 | | using Withdrawal for Withdrawal.Props;
57 | | using Order for Order.Props;
58 | | using Shift for Shift.Props;
59 | |
60 | | IDepositHandler public immutable depositHandler;
61 | | IWithdrawalHandler public immutable withdrawalHandler;
62 | | IShiftHandler public immutable shiftHandler;
63 | | IOrderHandler public immutable orderHandler;
64 | | IExternalHandler public immutable externalHandler;
65 | |
66 | | // @dev Constructor that initializes the contract with the provided Router, RoleStore, DataStore,
67 | | // EventEmitter, IDepositHandler, IWithdrawalHandler, IOrderHandler, and OrderStore instances
68 | | constructor(
69 | | Router _router,
70 | | RoleStore _roleStore,
71 | | DataStore _dataStore,
72 | | EventEmitter _eventEmitter,
73 | | IDepositHandler _depositHandler,
74 | | IWithdrawalHandler _withdrawalHandler,
75 | | IShiftHandler _shiftHandler,
76 | | IOrderHandler _orderHandler,
77 | | IExternalHandler _externalHandler
78 | | ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) {
79 | | depositHandler = _depositHandler;
80 | | withdrawalHandler = _withdrawalHandler;
81 | | shiftHandler = _shiftHandler;
82 | | orderHandler = _orderHandler;
83 | | externalHandler = _externalHandler;
84 | | }
85 | |
86 | | // makeExternalCalls can be used to perform an external swap before
87 | | // an action
88 | | // example:
89 | | // - ExchangeRouter.sendTokens(token: WETH, receiver: externalHandler, amount: 1e18)
90 | | // - ExchangeRouter.makeExternalCalls(
91 | | // WETH.approve(spender: aggregator, amount: 1e18),
92 | | // aggregator.swap(amount: 1, from: WETH, to: USDC, receiver: orderHandler)
93 | | // )
94 | | // - ExchangeRouter.createOrder
95 | | // the msg.sender for makeExternalCalls would be externalHandler
96 | | // refundTokens can be used to retrieve any excess tokens that may
97 | | // be left in the externalHandler
98 | | function makeExternalCalls(
99 | | address[] memory externalCallTargets,
100 | | bytes[] memory externalCallDataList,
101 | | address[] memory refundTokens,
102 | | address[] memory refundReceivers
103 | | ) external {
104 | | externalHandler.makeExternalCalls(
105 | | externalCallTargets,
106 | | externalCallDataList,
107 | | refundTokens,
108 | | refundReceivers
109 | | );
110 | | }
111 | |
112 | | /**
113 | | * @dev Creates a new deposit with the given long token, short token, long token amount, short token
114 | | * amount, and deposit parameters. The deposit is created by transferring the specified amounts of
115 | | * long and short tokens from the caller's account to the deposit store, and then calling the
116 | | * `createDeposit()` function on the deposit handler contract.
117 | | *
118 | | * @param params The deposit parameters, as specified in the `DepositUtils.CreateDepositParams` struct
119 | | * @return The unique ID of the newly created deposit
120 | | */
121 | * | function createDeposit(
122 | | DepositUtils.CreateDepositParams calldata params
123 | * | ) external payable override nonReentrant returns (bytes32) {
124 | * | address account = msg.sender;
125 | |
126 | * | return depositHandler.createDeposit(account, params);
127 | | }
128 | |
129 | * | function cancelDeposit(bytes32 key) external payable override nonReentrant {
130 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key);
131 | * | if (deposit.account() == address(0)) {
132 | | revert Errors.EmptyDeposit();
133 | | }
134 | |
135 | * | if (deposit.account() != msg.sender) {
136 | | revert Errors.Unauthorized(msg.sender, "account for cancelDeposit");
137 | | }
138 | |
139 | * | depositHandler.cancelDeposit(key);
140 | | }
141 | |
142 | | function simulateExecuteDeposit(
143 | | bytes32 key,
144 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams
145 | | ) external payable nonReentrant {
146 | | depositHandler.simulateExecuteDeposit(key, simulatedOracleParams);
147 | | }
148 | |
149 | * | function createWithdrawal(
150 | | WithdrawalUtils.CreateWithdrawalParams calldata params
151 | * | ) external payable override nonReentrant returns (bytes32) {
152 | * | address account = msg.sender;
153 | |
154 | * | return withdrawalHandler.createWithdrawal(account, params);
155 | | }
156 | |
157 | * | function cancelWithdrawal(
158 | | bytes32 key
159 | * | ) external payable override nonReentrant {
160 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(
161 | * | dataStore,
162 | * | key
163 | | );
164 | * | if (withdrawal.account() != msg.sender) {
165 | * | revert Errors.Unauthorized(
166 | * | msg.sender,
167 | | "account for cancelWithdrawal"
168 | | );
169 | | }
170 | |
171 | * | withdrawalHandler.cancelWithdrawal(key);
172 | | }
173 | |
174 | * | function executeAtomicWithdrawal(
175 | | WithdrawalUtils.CreateWithdrawalParams calldata params,
176 | | OracleUtils.SetPricesParams calldata oracleParams
177 | | ) external payable override nonReentrant {
178 | * | address account = msg.sender;
179 | |
180 | | return
181 | * | withdrawalHandler.executeAtomicWithdrawal(
182 | * | account,
183 | * | params,
184 | * | oracleParams
185 | | );
186 | | }
187 | |
188 | | function simulateExecuteWithdrawal(
189 | | bytes32 key,
190 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams,
191 | | ISwapPricingUtils.SwapPricingType swapPricingType
192 | | ) external payable nonReentrant {
193 | | withdrawalHandler.simulateExecuteWithdrawal(
194 | | key,
195 | | simulatedOracleParams,
196 | | swapPricingType
197 | | );
198 | | }
199 | |
200 | | function createShift(
201 | | ShiftUtils.CreateShiftParams calldata params
202 | | ) external payable override nonReentrant returns (bytes32) {
203 | | address account = msg.sender;
204 | |
205 | | return shiftHandler.createShift(account, params);
206 | | }
207 | |
208 | | function cancelShift(bytes32 key) external payable override nonReentrant {
209 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);
210 | | if (shift.account() != msg.sender) {
211 | | revert Errors.Unauthorized(msg.sender, "account for cancelShift");
212 | | }
213 | |
214 | | shiftHandler.cancelShift(key);
215 | | }
216 | |
217 | | function simulateExecuteShift(
218 | | bytes32 key,
219 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams
220 | | ) external payable nonReentrant {
221 | | shiftHandler.simulateExecuteShift(key, simulatedOracleParams);
222 | | }
223 | |
224 | | /**
225 | | * @dev Creates a new order with the given amount, order parameters. The order is
226 | | * created by transferring the specified amount of collateral tokens from the caller's account to the
227 | | * order store, and then calling the `createOrder()` function on the order handler contract. The
228 | | * referral code is also set on the caller's account using the referral storage contract.
229 | | */
230 | * | function createOrder(
231 | | IBaseOrderUtils.CreateOrderParams calldata params
232 | * | ) external payable override nonReentrant returns (bytes32) {
233 | * | address account = msg.sender;
234 | |
235 | * | return orderHandler.createOrder(account, params);
236 | | }
237 | |
238 | | //NOTE: FUZZ change
239 | |
240 | * | function createOrderFUZZ(
241 | | IBaseOrderUtils.CreateOrderParams calldata params
242 | | )
243 | | external
244 | | payable
245 | | override
246 | | nonReentrant
247 | * | returns (bool success, bytes32 key)
248 | | {
249 | * | address account = msg.sender;
250 | |
251 | * | try orderHandler.createOrder(account, params) returns (
252 | | bytes32 returnKey
253 | | ) {
254 | * | key = returnKey;
255 | * | success = true;
256 | | } catch {}
257 | |
258 | * | return (success, key);
259 | | }
260 | |
261 | | function setSavedCallbackContract(
262 | | address market,
263 | | address callbackContract
264 | | ) external payable nonReentrant {
265 | | // save the callback contract based on the account and market so that
266 | | // it can be called on liquidations and ADLs
267 | | CallbackUtils.setSavedCallbackContract(
268 | | dataStore,
269 | | msg.sender, // account
270 | | market,
271 | | callbackContract
272 | | );
273 | | }
274 | |
275 | | /**
276 | | * @dev Updates the given order with the specified size delta, acceptable price, and trigger price.
277 | | * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner
278 | | * of the order, and the order must not be a market order. The size delta, trigger price, and
279 | | * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is
280 | | * transferred to the contract is added to the order's execution fee. The updated order is then saved
281 | | * in the order store, and an `OrderUpdated` event is emitted.
282 | | *
283 | | * @param key The unique ID of the order to be updated
284 | | * @param sizeDeltaUsd The new size delta for the order
285 | | * @param acceptablePrice The new acceptable price for the order
286 | | * @param triggerPrice The new trigger price for the order
287 | | */
288 | | function updateOrder(
289 | | bytes32 key,
290 | | uint256 sizeDeltaUsd,
291 | | uint256 acceptablePrice,
292 | | uint256 triggerPrice,
293 | | uint256 minOutputAmount,
294 | | bool autoCancel
295 | | ) external payable nonReentrant {
296 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
297 | | if (order.account() != msg.sender) {
298 | | revert Errors.Unauthorized(msg.sender, "account for updateOrder");
299 | | }
300 | |
301 | | orderHandler.updateOrder(
302 | | key,
303 | | sizeDeltaUsd,
304 | | acceptablePrice,
305 | | triggerPrice,
306 | | minOutputAmount,
307 | | autoCancel,
308 | | order
309 | | );
310 | | }
311 | |
312 | | /**
313 | | * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order
314 | | * type. The caller must be the owner of the order, and the order must not be a market order. The
315 | | * order is cancelled by calling the `cancelOrder()` function in the `OrderUtils` contract. This
316 | | * function also records the starting gas amount and the reason for cancellation, which is passed to
317 | | * the `cancelOrder()` function.
318 | | *
319 | | * @param key The unique ID of the order to be cancelled
320 | | */
321 | * | function cancelOrder(bytes32 key) external payable nonReentrant {
322 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
323 | * | if (order.account() == address(0)) {
324 | | revert Errors.EmptyOrder();
325 | | }
326 | |
327 | * | if (order.account() != msg.sender) {
328 | | revert Errors.Unauthorized(msg.sender, "account for cancelOrder");
329 | | }
330 | |
331 | * | orderHandler.cancelOrder(key);
332 | | }
333 | |
334 | | function simulateExecuteOrder(
335 | | bytes32 key,
336 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams
337 | | ) external payable nonReentrant {
338 | | orderHandler.simulateExecuteOrder(key, simulatedOracleParams);
339 | | }
340 | |
341 | | /**
342 | | * @dev Claims funding fees for the given markets and tokens on behalf of the caller, and sends the
343 | | * fees to the specified receiver. The length of the `markets` and `tokens` arrays must be the same.
344 | | * For each market-token pair, the `claimFundingFees()` function in the `MarketUtils` contract is
345 | | * called to claim the fees for the caller.
346 | | *
347 | | * @param markets An array of market addresses
348 | | * @param tokens An array of token addresses, corresponding to the given markets
349 | | * @param receiver The address to which the claimed fees should be sent
350 | | */
351 | * | function claimFundingFees(
352 | | address[] memory markets,
353 | | address[] memory tokens,
354 | | address receiver
355 | * | ) external payable nonReentrant returns (uint256[] memory) {
356 | * | if (markets.length != tokens.length) {
357 | | revert Errors.InvalidClaimFundingFeesInput(
358 | | markets.length,
359 | | tokens.length
360 | | );
361 | | }
362 | |
363 | * | FeatureUtils.validateFeature(
364 | * | dataStore,
365 | * | Keys.claimFundingFeesFeatureDisabledKey(address(this))
366 | | );
367 | |
368 | * | AccountUtils.validateReceiver(receiver);
369 | |
370 | * | address account = msg.sender;
371 | |
372 | * | uint256[] memory claimedAmounts = new uint256[](markets.length);
373 | |
374 | * | for (uint256 i; i < markets.length; i++) {
375 | * | claimedAmounts[i] = MarketUtils.claimFundingFees(
376 | * | dataStore,
377 | * | eventEmitter,
378 | * | markets[i],
379 | * | tokens[i],
380 | * | account,
381 | * | receiver
382 | | );
383 | | }
384 | |
385 | * | return claimedAmounts;
386 | | }
387 | |
388 | | function claimCollateral(
389 | | address[] memory markets,
390 | | address[] memory tokens,
391 | | uint256[] memory timeKeys,
392 | | address receiver
393 | | ) external payable nonReentrant returns (uint256[] memory) {
394 | | if (
395 | | markets.length != tokens.length || tokens.length != timeKeys.length
396 | | ) {
397 | | revert Errors.InvalidClaimCollateralInput(
398 | | markets.length,
399 | | tokens.length,
400 | | timeKeys.length
401 | | );
402 | | }
403 | |
404 | | FeatureUtils.validateFeature(
405 | | dataStore,
406 | | Keys.claimCollateralFeatureDisabledKey(address(this))
407 | | );
408 | |
409 | | AccountUtils.validateReceiver(receiver);
410 | |
411 | | address account = msg.sender;
412 | |
413 | | uint256[] memory claimedAmounts = new uint256[](markets.length);
414 | |
415 | | for (uint256 i; i < markets.length; i++) {
416 | | claimedAmounts[i] = MarketUtils.claimCollateral(
417 | | dataStore,
418 | | eventEmitter,
419 | | markets[i],
420 | | tokens[i],
421 | | timeKeys[i],
422 | | account,
423 | | receiver
424 | | );
425 | | }
426 | |
427 | | return claimedAmounts;
428 | | }
429 | |
430 | | /**
431 | | * @dev Claims affiliate rewards for the given markets and tokens on behalf of the caller, and sends
432 | | * the rewards to the specified receiver. The length of the `markets` and `tokens` arrays must be
433 | | * the same. For each market-token pair, the `claimAffiliateReward()` function in the `ReferralUtils`
434 | | * contract is called to claim the rewards for the caller.
435 | | *
436 | | * @param markets An array of market addresses
437 | | * @param tokens An array of token addresses, corresponding to the given markets
438 | | * @param receiver The address to which the claimed rewards should be sent
439 | | */
440 | | function claimAffiliateRewards(
441 | | address[] memory markets,
442 | | address[] memory tokens,
443 | | address receiver
444 | | ) external payable nonReentrant returns (uint256[] memory) {
445 | | if (markets.length != tokens.length) {
446 | | revert Errors.InvalidClaimAffiliateRewardsInput(
447 | | markets.length,
448 | | tokens.length
449 | | );
450 | | }
451 | |
452 | | FeatureUtils.validateFeature(
453 | | dataStore,
454 | | Keys.claimAffiliateRewardsFeatureDisabledKey(address(this))
455 | | );
456 | |
457 | | address account = msg.sender;
458 | |
459 | | uint256[] memory claimedAmounts = new uint256[](markets.length);
460 | |
461 | | for (uint256 i; i < markets.length; i++) {
462 | | claimedAmounts[i] = ReferralUtils.claimAffiliateReward(
463 | | dataStore,
464 | | eventEmitter,
465 | | markets[i],
466 | | tokens[i],
467 | | account,
468 | | receiver
469 | | );
470 | | }
471 | |
472 | | return claimedAmounts;
473 | | }
474 | |
475 | | function setUiFeeFactor(uint256 uiFeeFactor) external payable nonReentrant {
476 | | address account = msg.sender;
477 | | MarketUtils.setUiFeeFactor(
478 | | dataStore,
479 | | eventEmitter,
480 | | account,
481 | | uiFeeFactor
482 | | );
483 | | }
484 | |
485 | | function claimUiFees(
486 | | address[] memory markets,
487 | | address[] memory tokens,
488 | | address receiver
489 | | ) external payable nonReentrant returns (uint256[] memory) {
490 | | if (markets.length != tokens.length) {
491 | | revert Errors.InvalidClaimUiFeesInput(
492 | | markets.length,
493 | | tokens.length
494 | | );
495 | | }
496 | |
497 | | FeatureUtils.validateFeature(
498 | | dataStore,
499 | | Keys.claimUiFeesFeatureDisabledKey(address(this))
500 | | );
501 | |
502 | | address uiFeeReceiver = msg.sender;
503 | |
504 | | uint256[] memory claimedAmounts = new uint256[](markets.length);
505 | |
506 | | for (uint256 i; i < markets.length; i++) {
507 | | claimedAmounts[i] = FeeUtils.claimUiFees(
508 | | dataStore,
509 | | eventEmitter,
510 | | uiFeeReceiver,
511 | | markets[i],
512 | | tokens[i],
513 | | receiver
514 | | );
515 | | }
516 | |
517 | | return claimedAmounts;
518 | | }
519 | | }
520 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/IExchangeRouter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../exchange/IDepositHandler.sol";
6 | | import "../exchange/IWithdrawalHandler.sol";
7 | | import "../exchange/IShiftHandler.sol";
8 | | import "../exchange/IOrderHandler.sol";
9 | | import "../exchange/IGlvHandler.sol";
10 | |
11 | | interface IExchangeRouter {
12 | | function createDeposit(
13 | | DepositUtils.CreateDepositParams calldata params
14 | | ) external payable returns (bytes32);
15 | |
16 | | function cancelDeposit(bytes32 key) external payable;
17 | |
18 | | function createWithdrawal(
19 | | WithdrawalUtils.CreateWithdrawalParams calldata params
20 | | ) external payable returns (bytes32);
21 | |
22 | | function cancelWithdrawal(bytes32 key) external payable;
23 | |
24 | | function executeAtomicWithdrawal(
25 | | WithdrawalUtils.CreateWithdrawalParams calldata params,
26 | | OracleUtils.SetPricesParams calldata oracleParams
27 | | ) external payable;
28 | |
29 | | function createShift(
30 | | ShiftUtils.CreateShiftParams calldata params
31 | | ) external payable returns (bytes32);
32 | |
33 | | function cancelShift(bytes32 key) external payable;
34 | |
35 | | function createOrder(
36 | | IBaseOrderUtils.CreateOrderParams calldata params
37 | | ) external payable returns (bytes32);
38 | |
39 | | //FUZZ ADDED
40 | | function createOrderFUZZ(
41 | | IBaseOrderUtils.CreateOrderParams calldata params
42 | | ) external payable returns (bool, bytes32);
43 | |
44 | | function updateOrder(
45 | | bytes32 key,
46 | | uint256 sizeDeltaUsd,
47 | | uint256 acceptablePrice,
48 | | uint256 triggerPrice,
49 | | uint256 minOutputAmount,
50 | | bool autoCancel
51 | | ) external payable;
52 | |
53 | | function cancelOrder(bytes32 key) external payable;
54 | | }
55 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/Router.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7 | |
8 | | import "../role/RoleModule.sol";
9 | |
10 | | /**
11 | | * @title Router
12 | | * @dev Users will approve this router for token spenditures
13 | | */
14 | * | contract Router is RoleModule {
15 | | using SafeERC20 for IERC20;
16 | |
17 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
18 | |
19 | | /**
20 | | * @dev transfer the specified amount of tokens from the account to the receiver
21 | | * @param token the token to transfer
22 | | * @param account the account to transfer from
23 | | * @param receiver the account to transfer to
24 | | * @param amount the amount of tokens to transfer
25 | | */
26 | * | function pluginTransfer(address token, address account, address receiver, uint256 amount) external onlyRouterPlugin {
27 | * | IERC20(token).safeTransferFrom(account, receiver, amount);
28 | | }
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/SubaccountRouter.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./BaseRouter.sol";
6 | | import "../exchange/IOrderHandler.sol";
7 | | import "../feature/FeatureUtils.sol";
8 | | import "../subaccount/SubaccountUtils.sol";
9 | | import "../order/OrderVault.sol";
10 | | import "../order/OrderStoreUtils.sol";
11 | |
12 | * | contract SubaccountRouter is BaseRouter {
13 | | using EventUtils for EventUtils.AddressItems;
14 | | using EventUtils for EventUtils.UintItems;
15 | | using EventUtils for EventUtils.IntItems;
16 | | using EventUtils for EventUtils.BoolItems;
17 | | using EventUtils for EventUtils.Bytes32Items;
18 | | using EventUtils for EventUtils.BytesItems;
19 | | using EventUtils for EventUtils.StringItems;
20 | |
21 | | using Order for Order.Props;
22 | |
23 | | IOrderHandler public immutable orderHandler;
24 | | OrderVault public immutable orderVault;
25 | |
26 | | constructor(
27 | | Router _router,
28 | | RoleStore _roleStore,
29 | | DataStore _dataStore,
30 | | EventEmitter _eventEmitter,
31 | | IOrderHandler _orderHandler,
32 | | OrderVault _orderVault
33 | | ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) {
34 | | orderHandler = _orderHandler;
35 | | orderVault = _orderVault;
36 | | }
37 | |
38 | | receive() external payable {
39 | | address wnt = TokenUtils.wnt(dataStore);
40 | | if (msg.sender != wnt) {
41 | | revert Errors.InvalidNativeTokenSender(msg.sender);
42 | | }
43 | | }
44 | |
45 | | function addSubaccount(address subaccount) external payable nonReentrant {
46 | | address account = msg.sender;
47 | | SubaccountUtils.addSubaccount(dataStore, eventEmitter, account, subaccount);
48 | | }
49 | |
50 | | function removeSubaccount(address subaccount) external payable nonReentrant {
51 | | address account = msg.sender;
52 | | SubaccountUtils.removeSubaccount(dataStore, eventEmitter, account, subaccount);
53 | | }
54 | |
55 | | function setMaxAllowedSubaccountActionCount(
56 | | address subaccount,
57 | | bytes32 actionType,
58 | | uint256 maxAllowedCount
59 | | ) external payable nonReentrant {
60 | | address account = msg.sender;
61 | |
62 | | SubaccountUtils.setMaxAllowedSubaccountActionCount(
63 | | dataStore,
64 | | eventEmitter,
65 | | account,
66 | | subaccount,
67 | | actionType,
68 | | maxAllowedCount
69 | | );
70 | | }
71 | |
72 | | function setSubaccountAutoTopUpAmount(
73 | | address subaccount,
74 | | uint256 amount
75 | | ) external payable nonReentrant {
76 | | address account = msg.sender;
77 | |
78 | | SubaccountUtils.setSubaccountAutoTopUpAmount(
79 | | dataStore,
80 | | eventEmitter,
81 | | account,
82 | | subaccount,
83 | | amount
84 | | );
85 | | }
86 | |
87 | | function createOrder(
88 | | address account,
89 | | IBaseOrderUtils.CreateOrderParams calldata params
90 | | ) external payable nonReentrant returns (bytes32) {
91 | | uint256 startingGas = gasleft();
92 | |
93 | | _handleSubaccountAction(account, Keys.SUBACCOUNT_ORDER_ACTION);
94 | |
95 | | if (params.addresses.receiver != account) {
96 | | revert Errors.InvalidReceiverForSubaccountOrder(params.addresses.receiver, account);
97 | | }
98 | |
99 | | if (
100 | | params.orderType == Order.OrderType.MarketSwap ||
101 | | params.orderType == Order.OrderType.LimitSwap ||
102 | | params.orderType == Order.OrderType.MarketIncrease ||
103 | | params.orderType == Order.OrderType.LimitIncrease
104 | | ) {
105 | | router.pluginTransfer(
106 | | params.addresses.initialCollateralToken, // token
107 | | account, // account
108 | | address(orderVault), // receiver
109 | | params.numbers.initialCollateralDeltaAmount // amount
110 | | );
111 | | }
112 | |
113 | | bytes32 key = orderHandler.createOrder(
114 | | account,
115 | | params
116 | | );
117 | |
118 | | _autoTopUpSubaccount(
119 | | account, // account
120 | | msg.sender, // subaccount
121 | | startingGas, // startingGas
122 | | params.numbers.executionFee // executionFee
123 | | );
124 | |
125 | | return key;
126 | | }
127 | |
128 | | function updateOrder(
129 | | bytes32 key,
130 | | uint256 sizeDeltaUsd,
131 | | uint256 acceptablePrice,
132 | | uint256 triggerPrice,
133 | | uint256 minOutputAmount,
134 | | bool autoCancel
135 | | ) external payable nonReentrant {
136 | | uint256 startingGas = gasleft();
137 | |
138 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
139 | |
140 | | if (order.account() == address(0)) { revert Errors.EmptyOrder(); }
141 | |
142 | | _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION);
143 | |
144 | | orderHandler.updateOrder(
145 | | key,
146 | | sizeDeltaUsd,
147 | | acceptablePrice,
148 | | triggerPrice,
149 | | minOutputAmount,
150 | | autoCancel,
151 | | order
152 | | );
153 | |
154 | | _autoTopUpSubaccount(
155 | | order.account(), // account
156 | | msg.sender, // subaccount
157 | | startingGas, // startingGas
158 | | 0 // executionFee
159 | | );
160 | | }
161 | |
162 | | function cancelOrder(
163 | | bytes32 key
164 | | ) external payable nonReentrant {
165 | | uint256 startingGas = gasleft();
166 | |
167 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key);
168 | |
169 | | if (order.account() == address(0)) { revert Errors.EmptyOrder(); }
170 | |
171 | | _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION);
172 | |
173 | | orderHandler.cancelOrder(key);
174 | |
175 | | _autoTopUpSubaccount(
176 | | order.account(), // account
177 | | msg.sender, // subaccount
178 | | startingGas, // startingGas
179 | | 0 // executionFee
180 | | );
181 | | }
182 | |
183 | | function _handleSubaccountAction(address account, bytes32 actionType) internal {
184 | | FeatureUtils.validateFeature(dataStore, Keys.subaccountFeatureDisabledKey(address(this)));
185 | |
186 | | address subaccount = msg.sender;
187 | | SubaccountUtils.validateSubaccount(dataStore, account, subaccount);
188 | |
189 | | SubaccountUtils.incrementSubaccountActionCount(
190 | | dataStore,
191 | | eventEmitter,
192 | | account,
193 | | subaccount,
194 | | actionType
195 | | );
196 | | }
197 | |
198 | | // the subaccount is topped up with wrapped native tokens
199 | | // the subaccount should separately unwrap the token as needed
200 | | function _autoTopUpSubaccount(address account, address subaccount, uint256 startingGas, uint256 executionFee) internal {
201 | | uint256 amount = SubaccountUtils.getSubaccountAutoTopUpAmount(dataStore, account, subaccount);
202 | | if (amount == 0) {
203 | | return;
204 | | }
205 | |
206 | | IERC20 wnt = IERC20(dataStore.getAddress(Keys.WNT));
207 | |
208 | | if (wnt.allowance(account, address(router)) < amount) { return; }
209 | | if (wnt.balanceOf(account) < amount) { return; }
210 | |
211 | | // cap the top up amount to the amount of native tokens used
212 | | uint256 nativeTokensUsed = (startingGas - gasleft()) * tx.gasprice + executionFee;
213 | | if (nativeTokensUsed < amount) { amount = nativeTokensUsed; }
214 | |
215 | | router.pluginTransfer(
216 | | address(wnt), // token
217 | | account, // account
218 | | address(this), // receiver
219 | | amount // amount
220 | | );
221 | |
222 | | TokenUtils.withdrawAndSendNativeToken(
223 | | dataStore,
224 | | address(wnt),
225 | | subaccount,
226 | | amount
227 | | );
228 | |
229 | | EventUtils.EventLogData memory eventData;
230 | |
231 | | eventData.addressItems.initItems(2);
232 | | eventData.addressItems.setItem(0, "account", account);
233 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
234 | |
235 | | eventData.uintItems.initItems(1);
236 | | eventData.uintItems.setItem(0, "amount", amount);
237 | |
238 | | eventEmitter.emitEventLog2(
239 | | "SubaccountAutoTopUp",
240 | | Cast.toBytes32(account),
241 | | Cast.toBytes32(subaccount),
242 | | eventData
243 | | );
244 | | }
245 | | }
246 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/Shift.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | * | library Shift {
6 | | struct Props {
7 | | Addresses addresses;
8 | | Numbers numbers;
9 | | }
10 | |
11 | | struct Addresses {
12 | | address account;
13 | | address receiver;
14 | | address callbackContract;
15 | | address uiFeeReceiver;
16 | | address fromMarket;
17 | | address toMarket;
18 | | }
19 | |
20 | | struct Numbers {
21 | | uint256 marketTokenAmount;
22 | | uint256 minMarketTokens;
23 | | uint256 updatedAtTime;
24 | | uint256 executionFee;
25 | | uint256 callbackGasLimit;
26 | | }
27 | |
28 | | function account(Props memory props) internal pure returns (address) {
29 | | return props.addresses.account;
30 | | }
31 | |
32 | | function setAccount(Props memory props, address value) internal pure {
33 | | props.addresses.account = value;
34 | | }
35 | |
36 | | function receiver(Props memory props) internal pure returns (address) {
37 | | return props.addresses.receiver;
38 | | }
39 | |
40 | | function setReceiver(Props memory props, address value) internal pure {
41 | | props.addresses.receiver = value;
42 | | }
43 | |
44 | | function callbackContract(Props memory props) internal pure returns (address) {
45 | | return props.addresses.callbackContract;
46 | | }
47 | |
48 | | function setCallbackContract(Props memory props, address value) internal pure {
49 | | props.addresses.callbackContract = value;
50 | | }
51 | |
52 | | function uiFeeReceiver(Props memory props) internal pure returns (address) {
53 | | return props.addresses.uiFeeReceiver;
54 | | }
55 | |
56 | | function setUiFeeReceiver(Props memory props, address value) internal pure {
57 | | props.addresses.uiFeeReceiver = value;
58 | | }
59 | |
60 | | function fromMarket(Props memory props) internal pure returns (address) {
61 | | return props.addresses.fromMarket;
62 | | }
63 | |
64 | | function setFromMarket(Props memory props, address value) internal pure {
65 | | props.addresses.fromMarket = value;
66 | | }
67 | |
68 | | function toMarket(Props memory props) internal pure returns (address) {
69 | | return props.addresses.toMarket;
70 | | }
71 | |
72 | | function setToMarket(Props memory props, address value) internal pure {
73 | | props.addresses.toMarket = value;
74 | | }
75 | |
76 | | function marketTokenAmount(Props memory props) internal pure returns (uint256) {
77 | | return props.numbers.marketTokenAmount;
78 | | }
79 | |
80 | | function setMarketTokenAmount(Props memory props, uint256 value) internal pure {
81 | | props.numbers.marketTokenAmount = value;
82 | | }
83 | |
84 | | function minMarketTokens(Props memory props) internal pure returns (uint256) {
85 | | return props.numbers.minMarketTokens;
86 | | }
87 | |
88 | | function setMinMarketTokens(Props memory props, uint256 value) internal pure {
89 | | props.numbers.minMarketTokens = value;
90 | | }
91 | |
92 | | function updatedAtTime(Props memory props) internal pure returns (uint256) {
93 | | return props.numbers.updatedAtTime;
94 | | }
95 | |
96 | | function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
97 | | props.numbers.updatedAtTime = value;
98 | | }
99 | |
100 | | function executionFee(Props memory props) internal pure returns (uint256) {
101 | | return props.numbers.executionFee;
102 | | }
103 | |
104 | | function setExecutionFee(Props memory props, uint256 value) internal pure {
105 | | props.numbers.executionFee = value;
106 | | }
107 | |
108 | | function callbackGasLimit(Props memory props) internal pure returns (uint256) {
109 | | return props.numbers.callbackGasLimit;
110 | | }
111 | |
112 | | function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
113 | | props.numbers.callbackGasLimit = value;
114 | | }
115 | |
116 | | }
117 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./Shift.sol";
10 | |
11 | * | library ShiftEventUtils {
12 | | using Shift for Shift.Props;
13 | |
14 | | using EventUtils for EventUtils.AddressItems;
15 | | using EventUtils for EventUtils.UintItems;
16 | | using EventUtils for EventUtils.IntItems;
17 | | using EventUtils for EventUtils.BoolItems;
18 | | using EventUtils for EventUtils.Bytes32Items;
19 | | using EventUtils for EventUtils.BytesItems;
20 | | using EventUtils for EventUtils.StringItems;
21 | |
22 | | function emitShiftCreated(
23 | | EventEmitter eventEmitter,
24 | | bytes32 key,
25 | | Shift.Props memory shift
26 | | ) internal {
27 | | EventUtils.EventLogData memory eventData;
28 | |
29 | | eventData.addressItems.initItems(5);
30 | | eventData.addressItems.setItem(0, "account", shift.account());
31 | | eventData.addressItems.setItem(1, "receiver", shift.receiver());
32 | | eventData.addressItems.setItem(2, "callbackContract", shift.callbackContract());
33 | | eventData.addressItems.setItem(3, "fromMarket", shift.fromMarket());
34 | | eventData.addressItems.setItem(4, "toMarket", shift.toMarket());
35 | |
36 | | eventData.uintItems.initItems(5);
37 | | eventData.uintItems.setItem(0, "marketTokenAmount", shift.marketTokenAmount());
38 | | eventData.uintItems.setItem(1, "minMarketTokens", shift.minMarketTokens());
39 | | eventData.uintItems.setItem(2, "updatedAtTime", shift.updatedAtTime());
40 | | eventData.uintItems.setItem(3, "executionFee", shift.executionFee());
41 | | eventData.uintItems.setItem(4, "callbackGasLimit", shift.callbackGasLimit());
42 | |
43 | | eventData.bytes32Items.initItems(1);
44 | | eventData.bytes32Items.setItem(0, "key", key);
45 | |
46 | | eventEmitter.emitEventLog2(
47 | | "ShiftCreated",
48 | | key,
49 | | Cast.toBytes32(shift.account()),
50 | | eventData
51 | | );
52 | | }
53 | |
54 | | function emitShiftExecuted(
55 | | EventEmitter eventEmitter,
56 | | bytes32 key,
57 | | address account,
58 | | uint256 receivedMarketTokens
59 | | ) internal {
60 | | EventUtils.EventLogData memory eventData;
61 | |
62 | | eventData.bytes32Items.initItems(1);
63 | | eventData.bytes32Items.setItem(0, "key", key);
64 | |
65 | | eventData.addressItems.initItems(1);
66 | | eventData.addressItems.setItem(0, "account", account);
67 | |
68 | | eventData.uintItems.initItems(1);
69 | | eventData.uintItems.setItem(0, "receivedMarketTokens", receivedMarketTokens);
70 | |
71 | | eventEmitter.emitEventLog2(
72 | | "ShiftExecuted",
73 | | key,
74 | | Cast.toBytes32(account),
75 | | eventData
76 | | );
77 | | }
78 | |
79 | | function emitShiftCancelled(
80 | | EventEmitter eventEmitter,
81 | | bytes32 key,
82 | | address account,
83 | | string memory reason,
84 | | bytes memory reasonBytes
85 | | ) internal {
86 | | EventUtils.EventLogData memory eventData;
87 | |
88 | | eventData.bytes32Items.initItems(1);
89 | | eventData.bytes32Items.setItem(0, "key", key);
90 | |
91 | | eventData.addressItems.initItems(1);
92 | | eventData.addressItems.setItem(0, "account", account);
93 | |
94 | | eventData.stringItems.initItems(1);
95 | | eventData.stringItems.setItem(0, "reason", reason);
96 | |
97 | | eventData.bytesItems.initItems(1);
98 | | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
99 | |
100 | | eventEmitter.emitEventLog2(
101 | | "ShiftCancelled",
102 | | key,
103 | | Cast.toBytes32(account),
104 | | eventData
105 | | );
106 | | }
107 | | }
108 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Shift.sol";
9 | |
10 | * | library ShiftStoreUtils {
11 | | using Shift for Shift.Props;
12 | |
13 | | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
14 | | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER"));
15 | | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
16 | | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
17 | | bytes32 internal constant FROM_MARKET = keccak256(abi.encode("FROM_MARKET"));
18 | | bytes32 internal constant TO_MARKET = keccak256(abi.encode("TO_MARKET"));
19 | |
20 | | bytes32 internal constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode("MARKET_TOKEN_AMOUNT"));
21 | | bytes32 internal constant MIN_MARKET_TOKENS = keccak256(abi.encode("MIN_MARKET_TOKENS"));
22 | | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME"));
23 | | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
24 | | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
25 | |
26 | | function get(DataStore dataStore, bytes32 key) internal view returns (Shift.Props memory) {
27 | | Shift.Props memory shift;
28 | | if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) {
29 | | return shift;
30 | | }
31 | |
32 | | shift.setAccount(dataStore.getAddress(
33 | | keccak256(abi.encode(key, ACCOUNT))
34 | | ));
35 | |
36 | | shift.setReceiver(dataStore.getAddress(
37 | | keccak256(abi.encode(key, RECEIVER))
38 | | ));
39 | |
40 | | shift.setCallbackContract(dataStore.getAddress(
41 | | keccak256(abi.encode(key, CALLBACK_CONTRACT))
42 | | ));
43 | |
44 | | shift.setUiFeeReceiver(dataStore.getAddress(
45 | | keccak256(abi.encode(key, UI_FEE_RECEIVER))
46 | | ));
47 | |
48 | | shift.setFromMarket(dataStore.getAddress(
49 | | keccak256(abi.encode(key, FROM_MARKET))
50 | | ));
51 | |
52 | | shift.setToMarket(dataStore.getAddress(
53 | | keccak256(abi.encode(key, TO_MARKET))
54 | | ));
55 | |
56 | | shift.setMarketTokenAmount(dataStore.getUint(
57 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
58 | | ));
59 | |
60 | | shift.setMinMarketTokens(dataStore.getUint(
61 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS))
62 | | ));
63 | |
64 | | shift.setUpdatedAtTime(dataStore.getUint(
65 | | keccak256(abi.encode(key, UPDATED_AT_TIME))
66 | | ));
67 | |
68 | | shift.setExecutionFee(dataStore.getUint(
69 | | keccak256(abi.encode(key, EXECUTION_FEE))
70 | | ));
71 | |
72 | | shift.setCallbackGasLimit(dataStore.getUint(
73 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
74 | | ));
75 | |
76 | | return shift;
77 | | }
78 | |
79 | | function set(DataStore dataStore, bytes32 key, Shift.Props memory shift) internal {
80 | | dataStore.addBytes32(
81 | | Keys.SHIFT_LIST,
82 | | key
83 | | );
84 | |
85 | | dataStore.addBytes32(
86 | | Keys.accountShiftListKey(shift.account()),
87 | | key
88 | | );
89 | |
90 | | dataStore.setAddress(
91 | | keccak256(abi.encode(key, ACCOUNT)),
92 | | shift.account()
93 | | );
94 | |
95 | | dataStore.setAddress(
96 | | keccak256(abi.encode(key, RECEIVER)),
97 | | shift.receiver()
98 | | );
99 | |
100 | | dataStore.setAddress(
101 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)),
102 | | shift.callbackContract()
103 | | );
104 | |
105 | | dataStore.setAddress(
106 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)),
107 | | shift.uiFeeReceiver()
108 | | );
109 | |
110 | | dataStore.setAddress(
111 | | keccak256(abi.encode(key, FROM_MARKET)),
112 | | shift.fromMarket()
113 | | );
114 | |
115 | | dataStore.setAddress(
116 | | keccak256(abi.encode(key, TO_MARKET)),
117 | | shift.toMarket()
118 | | );
119 | |
120 | | dataStore.setUint(
121 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),
122 | | shift.marketTokenAmount()
123 | | );
124 | |
125 | | dataStore.setUint(
126 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS)),
127 | | shift.minMarketTokens()
128 | | );
129 | |
130 | | dataStore.setUint(
131 | | keccak256(abi.encode(key, UPDATED_AT_TIME)),
132 | | shift.updatedAtTime()
133 | | );
134 | |
135 | | dataStore.setUint(
136 | | keccak256(abi.encode(key, EXECUTION_FEE)),
137 | | shift.executionFee()
138 | | );
139 | |
140 | | dataStore.setUint(
141 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
142 | | shift.callbackGasLimit()
143 | | );
144 | | }
145 | |
146 | | function remove(DataStore dataStore, bytes32 key, address account) internal {
147 | | if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) {
148 | | revert Errors.ShiftNotFound(key);
149 | | }
150 | |
151 | | dataStore.removeBytes32(
152 | | Keys.SHIFT_LIST,
153 | | key
154 | | );
155 | |
156 | | dataStore.removeBytes32(
157 | | Keys.accountShiftListKey(account),
158 | | key
159 | | );
160 | |
161 | | dataStore.removeAddress(
162 | | keccak256(abi.encode(key, ACCOUNT))
163 | | );
164 | |
165 | | dataStore.removeAddress(
166 | | keccak256(abi.encode(key, RECEIVER))
167 | | );
168 | |
169 | | dataStore.removeAddress(
170 | | keccak256(abi.encode(key, CALLBACK_CONTRACT))
171 | | );
172 | |
173 | | dataStore.removeAddress(
174 | | keccak256(abi.encode(key, UI_FEE_RECEIVER))
175 | | );
176 | |
177 | | dataStore.removeAddress(
178 | | keccak256(abi.encode(key, FROM_MARKET))
179 | | );
180 | |
181 | | dataStore.removeAddress(
182 | | keccak256(abi.encode(key, TO_MARKET))
183 | | );
184 | |
185 | | dataStore.removeUint(
186 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
187 | | );
188 | |
189 | | dataStore.removeUint(
190 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS))
191 | | );
192 | |
193 | | dataStore.removeUint(
194 | | keccak256(abi.encode(key, UPDATED_AT_TIME))
195 | | );
196 | |
197 | | dataStore.removeUint(
198 | | keccak256(abi.encode(key, EXECUTION_FEE))
199 | | );
200 | |
201 | | dataStore.removeUint(
202 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
203 | | );
204 | | }
205 | |
206 | | function getShiftCount(DataStore dataStore) internal view returns (uint256) {
207 | | return dataStore.getBytes32Count(Keys.SHIFT_LIST);
208 | | }
209 | |
210 | | function getShiftKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
211 | | return dataStore.getBytes32ValuesAt(Keys.SHIFT_LIST, start, end);
212 | | }
213 | |
214 | | function getAccountShiftCount(DataStore dataStore, address account) internal view returns (uint256) {
215 | | return dataStore.getBytes32Count(Keys.accountShiftListKey(account));
216 | | }
217 | |
218 | | function getAccountShiftKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
219 | | return dataStore.getBytes32ValuesAt(Keys.accountShiftListKey(account), start, end);
220 | | }
221 | | }
222 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/DataStore.sol";
6 | | import "../event/EventEmitter.sol";
7 | |
8 | | import "./ShiftVault.sol";
9 | | import "./ShiftStoreUtils.sol";
10 | | import "./ShiftEventUtils.sol";
11 | |
12 | | import "../nonce/NonceUtils.sol";
13 | |
14 | | import "../gas/GasUtils.sol";
15 | | import "../callback/CallbackUtils.sol";
16 | | import "../utils/AccountUtils.sol";
17 | |
18 | | import "../deposit/ExecuteDepositUtils.sol";
19 | | import "../withdrawal/ExecuteWithdrawalUtils.sol";
20 | |
21 | * | library ShiftUtils {
22 | | using Deposit for Deposit.Props;
23 | | using Withdrawal for Withdrawal.Props;
24 | | using Shift for Shift.Props;
25 | |
26 | | using EventUtils for EventUtils.AddressItems;
27 | | using EventUtils for EventUtils.UintItems;
28 | | using EventUtils for EventUtils.IntItems;
29 | | using EventUtils for EventUtils.BoolItems;
30 | | using EventUtils for EventUtils.Bytes32Items;
31 | | using EventUtils for EventUtils.BytesItems;
32 | | using EventUtils for EventUtils.StringItems;
33 | |
34 | | struct CreateShiftParams {
35 | | address receiver;
36 | | address callbackContract;
37 | | address uiFeeReceiver;
38 | | address fromMarket;
39 | | address toMarket;
40 | | uint256 minMarketTokens;
41 | | uint256 executionFee;
42 | | uint256 callbackGasLimit;
43 | | }
44 | |
45 | | struct CreateShiftCache {
46 | | uint256 estimatedGasLimit;
47 | | uint256 oraclePriceCount;
48 | | bytes32 key;
49 | | }
50 | |
51 | | struct ExecuteShiftParams {
52 | | DataStore dataStore;
53 | | EventEmitter eventEmitter;
54 | | ShiftVault shiftVault;
55 | | Oracle oracle;
56 | | bytes32 key;
57 | | address keeper;
58 | | uint256 startingGas;
59 | | }
60 | |
61 | | struct ExecuteShiftCache {
62 | | Withdrawal.Props withdrawal;
63 | | bytes32 withdrawalKey;
64 | | ExecuteWithdrawalUtils.ExecuteWithdrawalParams executeWithdrawalParams;
65 | | Market.Props depositMarket;
66 | | uint256 initialLongTokenAmount;
67 | | uint256 initialShortTokenAmount;
68 | | Deposit.Props deposit;
69 | | bytes32 depositKey;
70 | | ExecuteDepositUtils.ExecuteDepositParams executeDepositParams;
71 | | }
72 | |
73 | | function createShift(
74 | | DataStore dataStore,
75 | | EventEmitter eventEmitter,
76 | | ShiftVault shiftVault,
77 | | address account,
78 | | CreateShiftParams memory params
79 | | ) internal returns (bytes32) {
80 | | AccountUtils.validateAccount(account);
81 | |
82 | | if (params.fromMarket == params.toMarket) {
83 | | revert Errors.ShiftFromAndToMarketAreEqual(params.fromMarket);
84 | | }
85 | |
86 | | address wnt = TokenUtils.wnt(dataStore);
87 | | uint256 wntAmount = shiftVault.recordTransferIn(wnt);
88 | |
89 | | if (wntAmount < params.executionFee) {
90 | | revert Errors.InsufficientWntAmount(wntAmount, params.executionFee);
91 | | }
92 | |
93 | | AccountUtils.validateReceiver(params.receiver);
94 | |
95 | | uint256 marketTokenAmount = shiftVault.recordTransferIn(params.fromMarket);
96 | |
97 | | if (marketTokenAmount == 0) {
98 | | revert Errors.EmptyShiftAmount();
99 | | }
100 | |
101 | | params.executionFee = wntAmount;
102 | |
103 | | Market.Props memory fromMarket = MarketUtils.getEnabledMarket(dataStore, params.fromMarket);
104 | | Market.Props memory toMarket = MarketUtils.getEnabledMarket(dataStore, params.toMarket);
105 | |
106 | | if (fromMarket.longToken != toMarket.longToken) {
107 | | revert Errors.LongTokensAreNotEqual(fromMarket.longToken, toMarket.longToken);
108 | | }
109 | |
110 | | if (fromMarket.shortToken != toMarket.shortToken) {
111 | | revert Errors.ShortTokensAreNotEqual(fromMarket.shortToken, toMarket.shortToken);
112 | | }
113 | |
114 | | MarketUtils.validateEnabledMarket(dataStore, params.fromMarket);
115 | | MarketUtils.validateEnabledMarket(dataStore, params.toMarket);
116 | |
117 | | Shift.Props memory shift = Shift.Props(
118 | | Shift.Addresses(
119 | | account,
120 | | params.receiver,
121 | | params.callbackContract,
122 | | params.uiFeeReceiver,
123 | | params.fromMarket,
124 | | params.toMarket
125 | | ),
126 | | Shift.Numbers(
127 | | marketTokenAmount,
128 | | params.minMarketTokens,
129 | | Chain.currentTimestamp(),
130 | | params.executionFee,
131 | | params.callbackGasLimit
132 | | )
133 | | );
134 | |
135 | | CallbackUtils.validateCallbackGasLimit(dataStore, shift.callbackGasLimit());
136 | |
137 | | CreateShiftCache memory cache;
138 | |
139 | | cache.estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift);
140 | | cache.oraclePriceCount = GasUtils.estimateShiftOraclePriceCount();
141 | | GasUtils.validateExecutionFee(dataStore, cache.estimatedGasLimit, params.executionFee, cache.oraclePriceCount);
142 | |
143 | | cache.key = NonceUtils.getNextKey(dataStore);
144 | |
145 | | ShiftStoreUtils.set(dataStore, cache.key, shift);
146 | |
147 | | ShiftEventUtils.emitShiftCreated(eventEmitter, cache.key, shift);
148 | |
149 | | return cache.key;
150 | | }
151 | |
152 | | function executeShift(
153 | | ExecuteShiftParams memory params,
154 | | Shift.Props memory shift
155 | | ) internal {
156 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
157 | | params.startingGas -= gasleft() / 63;
158 | |
159 | | ShiftStoreUtils.remove(params.dataStore, params.key, shift.account());
160 | |
161 | | if (shift.account() == address(0)) {
162 | | revert Errors.EmptyShift();
163 | | }
164 | |
165 | | if (shift.marketTokenAmount() == 0) {
166 | | revert Errors.EmptyShiftAmount();
167 | | }
168 | |
169 | | ExecuteShiftCache memory cache;
170 | |
171 | | cache.depositMarket = MarketStoreUtils.get(params.dataStore, shift.toMarket());
172 | |
173 | | // if a user sends tokens directly to the shiftVault
174 | | // the recordTransferIn after the shift withdrawal would record
175 | | // these additional tokens and perform a deposit on the combined
176 | | // token amount (tokens directly sent + tokens withdrawn)
177 | | //
178 | | // a user could use this to avoid paying deposit fees
179 | | //
180 | | // call shiftVault.recordTransferIn before the withdrawal to prevent
181 | | // this
182 | | params.shiftVault.recordTransferIn(cache.depositMarket.longToken);
183 | | params.shiftVault.recordTransferIn(cache.depositMarket.shortToken);
184 | |
185 | | cache.withdrawal = Withdrawal.Props(
186 | | Withdrawal.Addresses(
187 | | shift.account(),
188 | | address(params.shiftVault), // receiver
189 | | address(0), // callbackContract
190 | | shift.uiFeeReceiver(), // uiFeeReceiver
191 | | shift.fromMarket(), // market
192 | | new address[](0), // longTokenSwapPath
193 | | new address[](0) // shortTokenSwapPath
194 | | ),
195 | | Withdrawal.Numbers(
196 | | shift.marketTokenAmount(),
197 | | 0, // minLongTokenAmount
198 | | 0, // minShortTokenAmount
199 | | 0, // updatedAtBlock
200 | | shift.updatedAtTime(),
201 | | 0, // executionFee
202 | | 0 // callbackGasLimit
203 | | ),
204 | | Withdrawal.Flags(
205 | | false
206 | | )
207 | | );
208 | |
209 | | cache.withdrawalKey = NonceUtils.getNextKey(params.dataStore);
210 | | params.dataStore.addBytes32(
211 | | Keys.WITHDRAWAL_LIST,
212 | | cache.withdrawalKey
213 | | );
214 | | WithdrawalEventUtils.emitWithdrawalCreated(
215 | | params.eventEmitter,
216 | | cache.withdrawalKey,
217 | | cache.withdrawal,
218 | | WithdrawalUtils.WithdrawalType.Shift
219 | | );
220 | |
221 | | cache.executeWithdrawalParams = ExecuteWithdrawalUtils.ExecuteWithdrawalParams(
222 | | params.dataStore,
223 | | params.eventEmitter,
224 | | WithdrawalVault(payable(params.shiftVault)),
225 | | params.oracle,
226 | | cache.withdrawalKey,
227 | | params.keeper,
228 | | params.startingGas,
229 | | ISwapPricingUtils.SwapPricingType.Shift
230 | | );
231 | |
232 | | ExecuteWithdrawalUtils.executeWithdrawal(
233 | | cache.executeWithdrawalParams,
234 | | cache.withdrawal
235 | | );
236 | |
237 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would
238 | | // be non-zero, the initialShortTokenAmount would be zero
239 | | cache.initialLongTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.longToken);
240 | | cache.initialShortTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.shortToken);
241 | |
242 | | // set the uiFeeReceiver to the zero address since the ui fee was already paid
243 | | // while executing the withdrawal
244 | | cache.deposit = Deposit.Props(
245 | | Deposit.Addresses(
246 | | shift.account(),
247 | | shift.receiver(),
248 | | address(0), // callbackContract
249 | | address(0), // uiFeeReceiver
250 | | shift.toMarket(), // market
251 | | cache.depositMarket.longToken, // initialLongToken
252 | | cache.depositMarket.shortToken, // initialShortToken
253 | | new address[](0), // longTokenSwapPath
254 | | new address[](0) // shortTokenSwapPath
255 | | ),
256 | | Deposit.Numbers(
257 | | cache.initialLongTokenAmount,
258 | | cache.initialShortTokenAmount,
259 | | shift.minMarketTokens(),
260 | | 0, // updatedAtBlock
261 | | shift.updatedAtTime(),
262 | | 0, // executionFee
263 | | 0 // callbackGasLimit
264 | | ),
265 | | Deposit.Flags(
266 | | false // shouldUnwrapNativeToken
267 | | )
268 | | );
269 | |
270 | | cache.depositKey = NonceUtils.getNextKey(params.dataStore);
271 | | params.dataStore.addBytes32(
272 | | Keys.DEPOSIT_LIST,
273 | | cache.depositKey
274 | | );
275 | | DepositEventUtils.emitDepositCreated(params.eventEmitter, cache.depositKey, cache.deposit, DepositUtils.DepositType.Shift);
276 | |
277 | | // price impact from changes in virtual inventory should be excluded
278 | | // since the action of withdrawing and depositing should not result in
279 | | // a net change of virtual inventory
280 | | cache.executeDepositParams = ExecuteDepositUtils.ExecuteDepositParams(
281 | | params.dataStore,
282 | | params.eventEmitter,
283 | | DepositVault(payable(params.shiftVault)),
284 | | params.oracle,
285 | | cache.depositKey,
286 | | params.keeper,
287 | | params.startingGas,
288 | | ISwapPricingUtils.SwapPricingType.Shift,
289 | | false // includeVirtualInventoryImpact
290 | | );
291 | |
292 | | uint256 receivedMarketTokens = ExecuteDepositUtils.executeDeposit(
293 | | cache.executeDepositParams,
294 | | cache.deposit
295 | | );
296 | |
297 | | ShiftEventUtils.emitShiftExecuted(
298 | | params.eventEmitter,
299 | | params.key,
300 | | shift.account(),
301 | | receivedMarketTokens
302 | | );
303 | |
304 | | EventUtils.EventLogData memory eventData;
305 | | eventData.uintItems.initItems(1);
306 | | eventData.uintItems.setItem(0, "receivedMarketTokens", receivedMarketTokens);
307 | | CallbackUtils.afterShiftExecution(params.key, shift, eventData);
308 | |
309 | | GasUtils.payExecutionFee(
310 | | params.dataStore,
311 | | params.eventEmitter,
312 | | params.shiftVault,
313 | | params.key,
314 | | shift.callbackContract(),
315 | | shift.executionFee(),
316 | | params.startingGas,
317 | | GasUtils.estimateShiftOraclePriceCount(),
318 | | params.keeper,
319 | | shift.receiver()
320 | | );
321 | | }
322 | |
323 | | function cancelShift(
324 | | DataStore dataStore,
325 | | EventEmitter eventEmitter,
326 | | ShiftVault shiftVault,
327 | | bytes32 key,
328 | | address keeper,
329 | | uint256 startingGas,
330 | | string memory reason,
331 | | bytes memory reasonBytes
332 | | ) internal {
333 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
334 | | startingGas -= gasleft() / 63;
335 | |
336 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key);
337 | |
338 | | if (shift.account() == address(0)) {
339 | | revert Errors.EmptyShift();
340 | | }
341 | |
342 | | if (shift.marketTokenAmount() == 0) {
343 | | revert Errors.EmptyShiftAmount();
344 | | }
345 | |
346 | | ShiftStoreUtils.remove(dataStore, key, shift.account());
347 | |
348 | | shiftVault.transferOut(
349 | | shift.fromMarket(),
350 | | shift.account(),
351 | | shift.marketTokenAmount(),
352 | | false // shouldUnwrapNativeToken
353 | | );
354 | |
355 | | ShiftEventUtils.emitShiftCancelled(
356 | | eventEmitter,
357 | | key,
358 | | shift.account(),
359 | | reason,
360 | | reasonBytes
361 | | );
362 | |
363 | | EventUtils.EventLogData memory eventData;
364 | | CallbackUtils.afterShiftCancellation(key, shift, eventData);
365 | |
366 | | GasUtils.payExecutionFee(
367 | | dataStore,
368 | | eventEmitter,
369 | | shiftVault,
370 | | key,
371 | | shift.callbackContract(),
372 | | shift.executionFee(),
373 | | startingGas,
374 | | GasUtils.estimateShiftOraclePriceCount(),
375 | | keeper,
376 | | shift.receiver()
377 | | );
378 | | }
379 | | }
380 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftVault.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../bank/StrictBank.sol";
6 | |
7 | * | contract ShiftVault is StrictBank {
8 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
9 | | }
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/subaccount/SubaccountUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../event/EventEmitter.sol";
8 | | import "../utils/Cast.sol";
9 | |
10 | * | library SubaccountUtils {
11 | | using EventUtils for EventUtils.AddressItems;
12 | | using EventUtils for EventUtils.UintItems;
13 | | using EventUtils for EventUtils.IntItems;
14 | | using EventUtils for EventUtils.BoolItems;
15 | | using EventUtils for EventUtils.Bytes32Items;
16 | | using EventUtils for EventUtils.BytesItems;
17 | | using EventUtils for EventUtils.StringItems;
18 | |
19 | | function addSubaccount(
20 | | DataStore dataStore,
21 | | EventEmitter eventEmitter,
22 | | address account,
23 | | address subaccount
24 | | ) internal {
25 | | bytes32 setKey = Keys.subaccountListKey(account);
26 | | dataStore.addAddress(setKey, subaccount);
27 | |
28 | | EventUtils.EventLogData memory eventData;
29 | |
30 | | eventData.addressItems.initItems(2);
31 | | eventData.addressItems.setItem(0, "account", account);
32 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
33 | |
34 | | eventEmitter.emitEventLog2(
35 | | "AddSubaccount",
36 | | Cast.toBytes32(account),
37 | | Cast.toBytes32(subaccount),
38 | | eventData
39 | | );
40 | | }
41 | |
42 | | function removeSubaccount(
43 | | DataStore dataStore,
44 | | EventEmitter eventEmitter,
45 | | address account,
46 | | address subaccount
47 | | ) internal {
48 | | bytes32 setKey = Keys.subaccountListKey(account);
49 | | dataStore.removeAddress(setKey, subaccount);
50 | |
51 | | EventUtils.EventLogData memory eventData;
52 | |
53 | | eventData.addressItems.initItems(2);
54 | | eventData.addressItems.setItem(0, "account", account);
55 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
56 | |
57 | | eventEmitter.emitEventLog2(
58 | | "RemoveSubaccount",
59 | | Cast.toBytes32(account),
60 | | Cast.toBytes32(subaccount),
61 | | eventData
62 | | );
63 | | }
64 | |
65 | | function incrementSubaccountActionCount(
66 | | DataStore dataStore,
67 | | EventEmitter eventEmitter,
68 | | address account,
69 | | address subaccount,
70 | | bytes32 actionType
71 | | ) internal {
72 | | bytes32 key = Keys.subaccountActionCountKey(account, subaccount, actionType);
73 | | uint256 nextValue = dataStore.incrementUint(key, 1);
74 | | validateSubaccountActionCount(dataStore, account, subaccount, actionType, nextValue);
75 | |
76 | | EventUtils.EventLogData memory eventData;
77 | |
78 | | eventData.addressItems.initItems(2);
79 | | eventData.addressItems.setItem(0, "account", account);
80 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
81 | |
82 | | eventData.uintItems.initItems(1);
83 | | eventData.uintItems.setItem(0, "nextValue", nextValue);
84 | |
85 | | eventData.bytes32Items.initItems(1);
86 | | eventData.bytes32Items.setItem(0, "actionType", actionType);
87 | |
88 | | eventEmitter.emitEventLog2(
89 | | "IncrementSubaccountActionCount",
90 | | Cast.toBytes32(account),
91 | | Cast.toBytes32(subaccount),
92 | | eventData
93 | | );
94 | | }
95 | |
96 | | function setMaxAllowedSubaccountActionCount(
97 | | DataStore dataStore,
98 | | EventEmitter eventEmitter,
99 | | address account,
100 | | address subaccount,
101 | | bytes32 actionType,
102 | | uint256 maxAllowedCount
103 | | ) internal {
104 | | bytes32 key = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType);
105 | | dataStore.setUint(key, maxAllowedCount);
106 | |
107 | | EventUtils.EventLogData memory eventData;
108 | |
109 | | eventData.addressItems.initItems(2);
110 | | eventData.addressItems.setItem(0, "account", account);
111 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
112 | |
113 | | eventData.uintItems.initItems(1);
114 | | eventData.uintItems.setItem(0, "maxAllowedCount", maxAllowedCount);
115 | |
116 | | eventEmitter.emitEventLog2(
117 | | "SetMaxAllowedSubaccountActionCount",
118 | | Cast.toBytes32(account),
119 | | Cast.toBytes32(subaccount),
120 | | eventData
121 | | );
122 | | }
123 | |
124 | | function validateSubaccountActionCount(
125 | | DataStore dataStore,
126 | | address account,
127 | | address subaccount,
128 | | bytes32 actionType,
129 | | uint256 count
130 | | ) internal view {
131 | | bytes32 key = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType);
132 | | uint256 maxCount = dataStore.getUint(key);
133 | | if (count > maxCount) {
134 | | revert Errors.MaxSubaccountActionCountExceeded(account, subaccount, count, maxCount);
135 | | }
136 | | }
137 | |
138 | | function validateSubaccount(
139 | | DataStore dataStore,
140 | | address account,
141 | | address subaccount
142 | | ) internal view {
143 | | bytes32 setKey = Keys.subaccountListKey(account);
144 | | if (!dataStore.containsAddress(setKey, subaccount)) {
145 | | revert Errors.SubaccountNotAuthorized(account, subaccount);
146 | | }
147 | | }
148 | |
149 | | function getSubaccountAutoTopUpAmount(
150 | | DataStore dataStore,
151 | | address account,
152 | | address subaccount
153 | | ) internal view returns (uint256) {
154 | | bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount);
155 | | return dataStore.getUint(key);
156 | | }
157 | |
158 | | function setSubaccountAutoTopUpAmount(
159 | | DataStore dataStore,
160 | | EventEmitter eventEmitter,
161 | | address account,
162 | | address subaccount,
163 | | uint256 amount
164 | | ) internal {
165 | | bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount);
166 | |
167 | | dataStore.setUint(key, amount);
168 | |
169 | | EventUtils.EventLogData memory eventData;
170 | |
171 | | eventData.addressItems.initItems(2);
172 | | eventData.addressItems.setItem(0, "account", account);
173 | | eventData.addressItems.setItem(1, "subaccount", subaccount);
174 | |
175 | | eventData.uintItems.initItems(1);
176 | | eventData.uintItems.setItem(0, "amount", amount);
177 | |
178 | | eventEmitter.emitEventLog2(
179 | | "SetSubaccountAutoTopUpAmount",
180 | | Cast.toBytes32(account),
181 | | Cast.toBytes32(subaccount),
182 | | eventData
183 | | );
184 | | }
185 | | }
186 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/swap/SwapHandler.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
6 | |
7 | | import "../role/RoleModule.sol";
8 | | import "./SwapUtils.sol";
9 | |
10 | | /**
11 | | * @title SwapHandler
12 | | * @dev A contract to help with swap functions
13 | | */
14 | * | contract SwapHandler is ReentrancyGuard, RoleModule {
15 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
16 | |
17 | | /**
18 | | * @dev perform a swap based on the given params
19 | | * @param params SwapUtils.SwapParams
20 | | * @return (outputToken, outputAmount)
21 | | */
22 | * | function swap(
23 | | SwapUtils.SwapParams memory params
24 | | )
25 | | external
26 | | nonReentrant
27 | | onlyController
28 | * | returns (address, uint256)
29 | | {
30 | * | return SwapUtils.swap(params);
31 | | }
32 | | }
33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/swap/SwapUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../adl/AdlUtils.sol";
6 | | import "../data/DataStore.sol";
7 | | import "../event/EventEmitter.sol";
8 | | import "../oracle/Oracle.sol";
9 | | import "../pricing/SwapPricingUtils.sol";
10 | | import "../token/TokenUtils.sol";
11 | | import "../fee/FeeUtils.sol";
12 | |
13 | | /**
14 | | * @title SwapUtils
15 | | * @dev Library for swap functions
16 | | */
17 | * | library SwapUtils {
18 | | using SafeCast for uint256;
19 | | using SafeCast for int256;
20 | | using Price for Price.Props;
21 | |
22 | | using EventUtils for EventUtils.AddressItems;
23 | | using EventUtils for EventUtils.UintItems;
24 | | using EventUtils for EventUtils.IntItems;
25 | | using EventUtils for EventUtils.BoolItems;
26 | | using EventUtils for EventUtils.Bytes32Items;
27 | | using EventUtils for EventUtils.BytesItems;
28 | | using EventUtils for EventUtils.StringItems;
29 | |
30 | | /**
31 | | * @param dataStore The contract that provides access to data stored on-chain.
32 | | * @param eventEmitter The contract that emits events.
33 | | * @param oracle The contract that provides access to price data from oracles.
34 | | * @param bank The contract providing the funds for the swap.
35 | | * @param key An identifying key for the swap.
36 | | * @param tokenIn The address of the token that is being swapped.
37 | | * @param amountIn The amount of the token that is being swapped.
38 | | * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed.
39 | | * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap.
40 | | * @param receiver The address to which the swapped tokens should be sent.
41 | | * @param uiFeeReceiver The address of the ui fee receiver.
42 | | * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.
43 | | */
44 | | struct SwapParams {
45 | | DataStore dataStore;
46 | | EventEmitter eventEmitter;
47 | | Oracle oracle;
48 | | Bank bank;
49 | | bytes32 key;
50 | | address tokenIn;
51 | | uint256 amountIn;
52 | | Market.Props[] swapPathMarkets;
53 | | uint256 minOutputAmount;
54 | | address receiver;
55 | | address uiFeeReceiver;
56 | | bool shouldUnwrapNativeToken;
57 | | }
58 | |
59 | | /**
60 | | * @param market The market in which the swap should be executed.
61 | | * @param tokenIn The address of the token that is being swapped.
62 | | * @param amountIn The amount of the token that is being swapped.
63 | | * @param receiver The address to which the swapped tokens should be sent.
64 | | * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped.
65 | | */
66 | | struct _SwapParams {
67 | | Market.Props market;
68 | | address tokenIn;
69 | | uint256 amountIn;
70 | | address receiver;
71 | | bool shouldUnwrapNativeToken;
72 | | }
73 | |
74 | | /**
75 | | * @param tokenOut The address of the token that is being received as part of the swap.
76 | | * @param tokenInPrice The price of the token that is being swapped.
77 | | * @param tokenOutPrice The price of the token that is being received as part of the swap.
78 | | * @param amountIn The amount of the token that is being swapped.
79 | | * @param amountOut The amount of the token that is being received as part of the swap.
80 | | * @param poolAmountOut The total amount of the token that is being received by all users in the swap pool.
81 | | */
82 | | struct SwapCache {
83 | | address tokenOut;
84 | | Price.Props tokenInPrice;
85 | | Price.Props tokenOutPrice;
86 | | uint256 amountIn;
87 | | uint256 amountInAfterFees;
88 | | uint256 amountOut;
89 | | uint256 poolAmountOut;
90 | | int256 priceImpactUsd;
91 | | int256 priceImpactAmount;
92 | | uint256 cappedDiffUsd;
93 | | int256 tokenInPriceImpactAmount;
94 | | }
95 | |
96 | | event SwapReverted(string reason, bytes reasonBytes);
97 | |
98 | | /**
99 | | * @dev Swaps a given amount of a given token for another token based on a
100 | | * specified swap path.
101 | | * @param params The parameters for the swap.
102 | | * @return A tuple containing the address of the token that was received as
103 | | * part of the swap and the amount of the received token.
104 | | */
105 | * | function swap(SwapParams memory params) internal returns (address, uint256) {
106 | * | if (params.amountIn == 0) {
107 | * | return (params.tokenIn, params.amountIn);
108 | | }
109 | |
110 | * | if (params.swapPathMarkets.length == 0) {
111 | * | if (params.amountIn < params.minOutputAmount) {
112 | | revert Errors.InsufficientOutputAmount(params.amountIn, params.minOutputAmount);
113 | | }
114 | |
115 | * | if (address(params.bank) != params.receiver) {
116 | * | params.bank.transferOut(
117 | * | params.tokenIn,
118 | * | params.receiver,
119 | * | params.amountIn,
120 | * | params.shouldUnwrapNativeToken
121 | | );
122 | | }
123 | |
124 | * | return (params.tokenIn, params.amountIn);
125 | | }
126 | |
127 | * | if (address(params.bank) != params.swapPathMarkets[0].marketToken) {
128 | * | params.bank.transferOut(
129 | * | params.tokenIn,
130 | * | params.swapPathMarkets[0].marketToken,
131 | * | params.amountIn,
132 | * | false
133 | | );
134 | | }
135 | |
136 | * | address tokenOut = params.tokenIn;
137 | * | uint256 outputAmount = params.amountIn;
138 | |
139 | * | for (uint256 i; i < params.swapPathMarkets.length; i++) {
140 | * | Market.Props memory market = params.swapPathMarkets[i];
141 | |
142 | * | bool flagExists = params.dataStore.getBool(Keys.swapPathMarketFlagKey(market.marketToken));
143 | * | if (flagExists) {
144 | | revert Errors.DuplicatedMarketInSwapPath(market.marketToken);
145 | | }
146 | |
147 | * | params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), true);
148 | |
149 | * | uint256 nextIndex = i + 1;
150 | * | address receiver;
151 | * | if (nextIndex < params.swapPathMarkets.length) {
152 | * | receiver = params.swapPathMarkets[nextIndex].marketToken;
153 | | } else {
154 | * | receiver = params.receiver;
155 | | }
156 | |
157 | * | _SwapParams memory _params = _SwapParams(
158 | * | market,
159 | * | tokenOut,
160 | * | outputAmount,
161 | * | receiver,
162 | * | i == params.swapPathMarkets.length - 1 ? params.shouldUnwrapNativeToken : false // only convert ETH on the last swap if needed
163 | | );
164 | |
165 | * | (tokenOut, outputAmount) = _swap(params, _params);
166 | | }
167 | |
168 | * | for (uint256 i; i < params.swapPathMarkets.length; i++) {
169 | * | Market.Props memory market = params.swapPathMarkets[i];
170 | * | params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), false);
171 | | }
172 | |
173 | * | if (outputAmount < params.minOutputAmount) {
174 | | revert Errors.InsufficientSwapOutputAmount(outputAmount, params.minOutputAmount);
175 | | }
176 | |
177 | * | return (tokenOut, outputAmount);
178 | | }
179 | |
180 | | function validateSwapOutputToken(
181 | | DataStore dataStore,
182 | | address[] memory swapPath,
183 | | address inputToken,
184 | | address expectedOutputToken
185 | | ) internal view {
186 | | address outputToken = getOutputToken(dataStore, swapPath, inputToken);
187 | | if (outputToken != expectedOutputToken) {
188 | | revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken);
189 | | }
190 | | }
191 | |
192 | | function getOutputToken(
193 | | DataStore dataStore,
194 | | address[] memory swapPath,
195 | | address inputToken
196 | | ) internal view returns (address) {
197 | | address outputToken = inputToken;
198 | | Market.Props[] memory markets = MarketUtils.getSwapPathMarkets(dataStore, swapPath);
199 | | uint256 marketCount = markets.length;
200 | |
201 | | for (uint256 i; i < marketCount; i++) {
202 | | Market.Props memory market = markets[i];
203 | | outputToken = MarketUtils.getOppositeToken(outputToken, market);
204 | | }
205 | |
206 | | return outputToken;
207 | | }
208 | |
209 | | /**
210 | | * Performs a swap on a single market.
211 | | *
212 | | * @param params The parameters for the swap.
213 | | * @param _params The parameters for the swap on this specific market.
214 | | * @return The token and amount that was swapped.
215 | | */
216 | * | function _swap(SwapParams memory params, _SwapParams memory _params) internal returns (address, uint256) {
217 | * | SwapCache memory cache;
218 | |
219 | * | if (_params.tokenIn != _params.market.longToken && _params.tokenIn != _params.market.shortToken) {
220 | * | revert Errors.InvalidTokenIn(_params.tokenIn, _params.market.marketToken);
221 | | }
222 | |
223 | * | MarketUtils.validateSwapMarket(params.dataStore, _params.market);
224 | |
225 | * | cache.tokenOut = MarketUtils.getOppositeToken(_params.tokenIn, _params.market);
226 | * | cache.tokenInPrice = params.oracle.getPrimaryPrice(_params.tokenIn);
227 | * | cache.tokenOutPrice = params.oracle.getPrimaryPrice(cache.tokenOut);
228 | |
229 | | // note that this may not be entirely accurate since the effect of the
230 | | // swap fees are not accounted for
231 | * | cache.priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
232 | * | SwapPricingUtils.GetPriceImpactUsdParams(
233 | * | params.dataStore,
234 | * | _params.market,
235 | * | _params.tokenIn,
236 | * | cache.tokenOut,
237 | * | cache.tokenInPrice.midPrice(),
238 | * | cache.tokenOutPrice.midPrice(),
239 | * | (_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(),
240 | * | -(_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(),
241 | * | true // includeVirtualInventoryImpact
242 | | )
243 | | );
244 | |
245 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(
246 | * | params.dataStore,
247 | * | _params.market.marketToken,
248 | * | _params.amountIn,
249 | * | cache.priceImpactUsd > 0, // forPositiveImpact
250 | * | params.uiFeeReceiver,
251 | * | ISwapPricingUtils.SwapPricingType.TwoStep
252 | | );
253 | |
254 | * | FeeUtils.incrementClaimableFeeAmount(
255 | * | params.dataStore,
256 | * | params.eventEmitter,
257 | * | _params.market.marketToken,
258 | * | _params.tokenIn,
259 | * | fees.feeReceiverAmount,
260 | | Keys.SWAP_FEE_TYPE
261 | | );
262 | |
263 | * | FeeUtils.incrementClaimableUiFeeAmount(
264 | * | params.dataStore,
265 | * | params.eventEmitter,
266 | * | params.uiFeeReceiver,
267 | * | _params.market.marketToken,
268 | * | _params.tokenIn,
269 | * | fees.uiFeeAmount,
270 | | Keys.UI_SWAP_FEE_TYPE
271 | | );
272 | |
273 | * | if (cache.priceImpactUsd > 0) {
274 | | // when there is a positive price impact factor, additional tokens from the swap impact pool
275 | | // are withdrawn for the user
276 | | // for example, if 50,000 USDC is swapped out and there is a positive price impact
277 | | // an additional 100 USDC may be sent to the user
278 | | // the swap impact pool is decreased by the used amount
279 | |
280 | | cache.amountIn = fees.amountAfterFees;
281 | |
282 | | (cache.priceImpactAmount, cache.cappedDiffUsd) = MarketUtils.applySwapImpactWithCap(
283 | | params.dataStore,
284 | | params.eventEmitter,
285 | | _params.market.marketToken,
286 | | cache.tokenOut,
287 | | cache.tokenOutPrice,
288 | | cache.priceImpactUsd
289 | | );
290 | |
291 | | // if the positive price impact was capped, use the tokenIn swap
292 | | // impact pool to pay for the positive price impact
293 | | if (cache.cappedDiffUsd != 0) {
294 | | (cache.tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(
295 | | params.dataStore,
296 | | params.eventEmitter,
297 | | _params.market.marketToken,
298 | | _params.tokenIn,
299 | | cache.tokenInPrice,
300 | | cache.cappedDiffUsd.toInt256()
301 | | );
302 | |
303 | | // this additional amountIn is already in the Market
304 | | // it is subtracted from the swap impact pool amount
305 | | // and the market pool amount is increased by the updated
306 | | // amountIn below
307 | | cache.amountIn += cache.tokenInPriceImpactAmount.toUint256();
308 | | }
309 | |
310 | | // round amountOut down
311 | | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
312 | | cache.poolAmountOut = cache.amountOut;
313 | |
314 | | // the below amount is subtracted from the swap impact pool instead of the market pool amount
315 | | cache.amountOut += cache.priceImpactAmount.toUint256();
316 | | } else {
317 | | // when there is a negative price impact factor,
318 | | // less of the input amount is sent to the pool
319 | | // for example, if 10 ETH is swapped in and there is a negative price impact
320 | | // only 9.995 ETH may be swapped in
321 | | // the remaining 0.005 ETH will be stored in the swap impact pool
322 | |
323 | * | (cache.priceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap(
324 | * | params.dataStore,
325 | * | params.eventEmitter,
326 | * | _params.market.marketToken,
327 | * | _params.tokenIn,
328 | * | cache.tokenInPrice,
329 | * | cache.priceImpactUsd
330 | | );
331 | |
332 | * | if (fees.amountAfterFees <= (-cache.priceImpactAmount).toUint256()) {
333 | | revert Errors.SwapPriceImpactExceedsAmountIn(fees.amountAfterFees, cache.priceImpactAmount);
334 | | }
335 | |
336 | * | cache.amountIn = fees.amountAfterFees - (-cache.priceImpactAmount).toUint256();
337 | * | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
338 | * | cache.poolAmountOut = cache.amountOut;
339 | | }
340 | |
341 | | // the amountOut value includes the positive price impact amount
342 | * | if (_params.receiver != _params.market.marketToken) {
343 | * | MarketToken(payable(_params.market.marketToken)).transferOut(
344 | * | cache.tokenOut,
345 | * | _params.receiver,
346 | * | cache.amountOut,
347 | * | _params.shouldUnwrapNativeToken
348 | | );
349 | | }
350 | |
351 | * | MarketUtils.applyDeltaToPoolAmount(
352 | * | params.dataStore,
353 | * | params.eventEmitter,
354 | * | _params.market,
355 | * | _params.tokenIn,
356 | * | (cache.amountIn + fees.feeAmountForPool).toInt256()
357 | | );
358 | |
359 | | // the poolAmountOut excludes the positive price impact amount
360 | | // as that is deducted from the swap impact pool instead
361 | * | MarketUtils.applyDeltaToPoolAmount(
362 | * | params.dataStore,
363 | * | params.eventEmitter,
364 | * | _params.market,
365 | * | cache.tokenOut,
366 | * | -cache.poolAmountOut.toInt256()
367 | | );
368 | |
369 | * | MarketUtils.MarketPrices memory prices = MarketUtils.MarketPrices(
370 | * | params.oracle.getPrimaryPrice(_params.market.indexToken),
371 | * | _params.tokenIn == _params.market.longToken ? cache.tokenInPrice : cache.tokenOutPrice,
372 | * | _params.tokenIn == _params.market.shortToken ? cache.tokenInPrice : cache.tokenOutPrice
373 | | );
374 | |
375 | * | MarketUtils.validatePoolAmount(
376 | * | params.dataStore,
377 | * | _params.market,
378 | * | _params.tokenIn
379 | | );
380 | |
381 | | // for single token markets cache.tokenOut will always equal _params.market.longToken
382 | | // so only the reserve for longs will be validated
383 | | // swaps should be disabled for single token markets so this should not be an issue
384 | * | MarketUtils.validateReserve(
385 | * | params.dataStore,
386 | * | _params.market,
387 | * | prices,
388 | * | cache.tokenOut == _params.market.longToken
389 | | );
390 | |
391 | * | MarketUtils.validateMaxPnl(
392 | * | params.dataStore,
393 | * | _params.market,
394 | * | prices,
395 | * | _params.tokenIn == _params.market.longToken ? Keys.MAX_PNL_FACTOR_FOR_DEPOSITS : Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
396 | * | cache.tokenOut == _params.market.shortToken ? Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS : Keys.MAX_PNL_FACTOR_FOR_DEPOSITS
397 | | );
398 | |
399 | * | SwapPricingUtils.EmitSwapInfoParams memory emitSwapInfoParams;
400 | |
401 | * | emitSwapInfoParams.orderKey = params.key;
402 | * | emitSwapInfoParams.market = _params.market.marketToken;
403 | * | emitSwapInfoParams.receiver = _params.receiver;
404 | * | emitSwapInfoParams.tokenIn = _params.tokenIn;
405 | * | emitSwapInfoParams.tokenOut = cache.tokenOut;
406 | * | emitSwapInfoParams.tokenInPrice = cache.tokenInPrice.min;
407 | * | emitSwapInfoParams.tokenOutPrice = cache.tokenOutPrice.max;
408 | * | emitSwapInfoParams.amountIn = _params.amountIn;
409 | * | emitSwapInfoParams.amountInAfterFees = fees.amountAfterFees;
410 | * | emitSwapInfoParams.amountOut = cache.amountOut;
411 | * | emitSwapInfoParams.priceImpactUsd = cache.priceImpactUsd;
412 | * | emitSwapInfoParams.priceImpactAmount = cache.priceImpactAmount;
413 | * | emitSwapInfoParams.tokenInPriceImpactAmount = cache.tokenInPriceImpactAmount;
414 | |
415 | * | SwapPricingUtils.emitSwapInfo(
416 | * | params.eventEmitter,
417 | * | emitSwapInfoParams
418 | | );
419 | |
420 | * | SwapPricingUtils.emitSwapFeesCollected(
421 | * | params.eventEmitter,
422 | * | params.key,
423 | * | _params.market.marketToken,
424 | * | _params.tokenIn,
425 | * | cache.tokenInPrice.min,
426 | | Keys.SWAP_FEE_TYPE,
427 | * | fees
428 | | );
429 | |
430 | * | return (cache.tokenOut, cache.amountOut);
431 | | }
432 | | }
433 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/ArrayTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../utils/Array.sol";
7 | |
8 | | /**
9 | | * @title ArrayTest
10 | | * @dev Contract to help test the Array library
11 | | */
12 | * | contract ArrayTest {
13 | | function getMedian(uint256[] memory arr) internal pure returns (uint256) {
14 | | return Array.getMedian(arr);
15 | | }
16 | | }
17 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/DepositStoreUtilsTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../deposit/DepositStoreUtils.sol";
7 | |
8 | | /**
9 | | * @title DepositeStoreUtilsTest
10 | | * @dev Contract to help test the DepositStoreUtils library
11 | | */
12 | * | contract DepositStoreUtilsTest {
13 | | function getEmptyDeposit() internal pure returns (Deposit.Props memory) {
14 | | Deposit.Props memory deposit;
15 | | return deposit;
16 | | }
17 | |
18 | | function setDeposit(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) internal {
19 | | DepositStoreUtils.set(dataStore, key, deposit);
20 | | }
21 | |
22 | | function removeDeposit(DataStore dataStore, bytes32 key, address account) internal {
23 | | DepositStoreUtils.remove(dataStore, key, account);
24 | | }
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/GasUsageTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | /**
7 | | * @title GasUsageTest
8 | | */
9 | * | contract GasUsageTest {
10 | | function getGasUsageForExternalLibraryCall() internal view returns (uint256, uint256) {
11 | | uint256 startingGas = gasleft();
12 | | uint256 gasLeft = GasUsageTestLib.getGasLeft();
13 | | return (startingGas, gasLeft);
14 | | }
15 | | }
16 | |
17 | * | library GasUsageTestLib {
18 | | function getGasLeft() internal view returns (uint256) {
19 | | return gasleft();
20 | | }
21 | | }
22 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/MarketStoreUtilsTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../market/MarketStoreUtils.sol";
7 | |
8 | | /**
9 | | * @title MarketStoreUtilsTest
10 | | * @dev Contract to help test the MarketStoreUtils library
11 | | */
12 | * | contract MarketStoreUtilsTest {
13 | | function getEmptyMarket() internal pure returns (Market.Props memory) {
14 | | Market.Props memory market;
15 | | return market;
16 | | }
17 | |
18 | | function setMarket(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) internal {
19 | | MarketStoreUtils.set(dataStore, key, salt, market);
20 | | }
21 | |
22 | | function removeMarket(DataStore dataStore, address key) internal {
23 | | MarketStoreUtils.remove(dataStore, key);
24 | | }
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/OrderStoreUtilsTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../order/OrderStoreUtils.sol";
7 | |
8 | | /**
9 | | * @title OrderStoreUtilsTest
10 | | * @dev Contract to help test the OrderStoreUtils library
11 | | */
12 | * | contract OrderStoreUtilsTest {
13 | | function getEmptyOrder() internal pure returns (Order.Props memory) {
14 | | Order.Props memory order;
15 | | return order;
16 | | }
17 | |
18 | | function setOrder(DataStore dataStore, bytes32 key, Order.Props memory order) internal {
19 | | OrderStoreUtils.set(dataStore, key, order);
20 | | }
21 | |
22 | | function removeOrder(DataStore dataStore, bytes32 key, address account) internal {
23 | | OrderStoreUtils.remove(dataStore, key, account);
24 | | }
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/PositionStoreUtilsTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../position/PositionStoreUtils.sol";
7 | |
8 | | /**
9 | | * @title PositionStoreUtilsTest
10 | | * @dev Contract to help test the PositionStoreUtils library
11 | | */
12 | * | contract PositionStoreUtilsTest {
13 | | function getEmptyPosition() internal pure returns (Position.Props memory) {
14 | | Position.Props memory position;
15 | | return position;
16 | | }
17 | |
18 | | function setPosition(DataStore dataStore, bytes32 key, Position.Props memory position) internal {
19 | | PositionStoreUtils.set(dataStore, key, position);
20 | | }
21 | |
22 | | function removePosition(DataStore dataStore, bytes32 key, address account) internal {
23 | | PositionStoreUtils.remove(dataStore, key, account);
24 | | }
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/PricingUtilsTest.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../pricing/PricingUtils.sol";
6 | |
7 | | /**
8 | | * @title PricingUtilsTest
9 | | * @dev Contract to help test the PricingUtils library
10 | | */
11 | * | contract PricingUtilsTest {
12 | | function applyImpactFactor(
13 | | uint256 diffUsd,
14 | | uint256 impactFactor,
15 | | uint256 impactExponentFactor
16 | | ) internal pure returns (uint256) {
17 | | return PricingUtils.applyImpactFactor(diffUsd, impactFactor, impactExponentFactor);
18 | | }
19 | | }
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/WithdrawalStoreUtilsTest.sol
1 | |
2 | | // SPDX-License-Identifier: BUSL-1.1
3 | |
4 | | pragma solidity ^0.8.0;
5 | |
6 | | import "../withdrawal/WithdrawalStoreUtils.sol";
7 | |
8 | | /**
9 | | * @title WithdrawalStoreUtilsTest
10 | | * @dev Contract to help test the WithdrawalStoreUtils library
11 | | */
12 | * | contract WithdrawalStoreUtilsTest {
13 | | function getEmptyWithdrawal() internal pure returns (Withdrawal.Props memory) {
14 | | Withdrawal.Props memory withdrawal;
15 | | return withdrawal;
16 | | }
17 | |
18 | | function setWithdrawal(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) internal {
19 | | WithdrawalStoreUtils.set(dataStore, key, withdrawal);
20 | | }
21 | |
22 | | function removeWithdrawal(DataStore dataStore, bytes32 key, address account) internal {
23 | | WithdrawalStoreUtils.remove(dataStore, key, account);
24 | | }
25 | | }
26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/token/IWNT.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @title IWNT
7 | | * @dev Interface for Wrapped Native Tokens, e.g. WETH
8 | | * The contract is named WNT instead of WETH for a more general reference name
9 | | * that can be used on any blockchain
10 | | */
11 | | interface IWNT {
12 | | function deposit() external payable;
13 | | function withdraw(uint256 amount) external;
14 | | }
15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/token/TokenUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/Address.sol";
6 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8 | |
9 | | import "../data/DataStore.sol";
10 | | import "../data/Keys.sol";
11 | | import "../error/ErrorUtils.sol";
12 | | import "../utils/AccountUtils.sol";
13 | |
14 | | import "./IWNT.sol";
15 | |
16 | | /**
17 | | * @title TokenUtils
18 | | * @dev Library for token functions, helps with transferring of tokens and
19 | | * native token functions
20 | | */
21 | * | library TokenUtils {
22 | | using Address for address;
23 | | using SafeERC20 for IERC20;
24 | |
25 | | event TokenTransferReverted(string reason, bytes returndata);
26 | | event NativeTokenTransferReverted(string reason);
27 | |
28 | | /**
29 | | * @dev Returns the address of the WNT token.
30 | | * @param dataStore DataStore contract instance where the address of the WNT token is stored.
31 | | * @return The address of the WNT token.
32 | | */
33 | * | function wnt(DataStore dataStore) internal view returns (address) {
34 | * | return dataStore.getAddress(Keys.WNT);
35 | | }
36 | |
37 | | /**
38 | | * @dev Transfers the specified amount of `token` from the caller to `receiver`.
39 | | * limit the amount of gas forwarded so that a user cannot intentionally
40 | | * construct a token call that would consume all gas and prevent necessary
41 | | * actions like request cancellation from being executed
42 | | *
43 | | * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`.
44 | | * @param token The address of the ERC20 token that is being transferred.
45 | | * @param receiver The address of the recipient of the `token` transfer.
46 | | * @param amount The amount of `token` to transfer.
47 | | */
48 | * | function transfer(
49 | | DataStore dataStore,
50 | | address token,
51 | | address receiver,
52 | | uint256 amount
53 | | ) internal {
54 | * | if (amount == 0) { return; }
55 | * | AccountUtils.validateReceiver(receiver);
56 | |
57 | * | uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));
58 | * | if (gasLimit == 0) {
59 | | revert Errors.EmptyTokenTranferGasLimit(token);
60 | | }
61 | |
62 | * | (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit(
63 | * | IERC20(token),
64 | * | receiver,
65 | * | amount,
66 | * | gasLimit
67 | | );
68 | |
69 | * | if (success0) { return; }
70 | |
71 | | address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);
72 | |
73 | | if (holdingAddress == address(0)) {
74 | | revert Errors.EmptyHoldingAddress();
75 | | }
76 | |
77 | | // in case transfers to the receiver fail due to blacklisting or other reasons
78 | | // send the tokens to a holding address to avoid possible gaming through reverting
79 | | // transfers
80 | | (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(
81 | | IERC20(token),
82 | | holdingAddress,
83 | | amount,
84 | | gasLimit
85 | | );
86 | |
87 | | if (success1) { return; }
88 | |
89 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata);
90 | | emit TokenTransferReverted(reason, returndata);
91 | |
92 | | // throw custom errors to prevent spoofing of errors
93 | | // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler
94 | | // do not cancel requests for specific errors
95 | | revert Errors.TokenTransferError(token, receiver, amount);
96 | | }
97 | |
98 | | function sendNativeToken(
99 | | DataStore dataStore,
100 | | address receiver,
101 | | uint256 amount
102 | | ) internal {
103 | | if (amount == 0) { return; }
104 | |
105 | | AccountUtils.validateReceiver(receiver);
106 | |
107 | | uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);
108 | |
109 | | bool success;
110 | | // use an assembly call to avoid loading large data into memory
111 | | // input mem[in…(in+insize)]
112 | | // output area mem[out…(out+outsize))]
113 | | assembly {
114 | | success := call(
115 | | gasLimit, // gas limit
116 | | receiver, // receiver
117 | | amount, // value
118 | | 0, // in
119 | | 0, // insize
120 | | 0, // out
121 | | 0 // outsize
122 | | )
123 | | }
124 | |
125 | | if (success) { return; }
126 | |
127 | | // if the transfer failed, re-wrap the token and send it to the receiver
128 | | depositAndSendWrappedNativeToken(
129 | | dataStore,
130 | | receiver,
131 | | amount
132 | | );
133 | | }
134 | |
135 | | /**
136 | | * Deposits the specified amount of native token and sends the specified
137 | | * amount of wrapped native token to the specified receiver address.
138 | | *
139 | | * @param dataStore the data store to use for storing and retrieving data
140 | | * @param receiver the address of the recipient of the wrapped native token transfer
141 | | * @param amount the amount of native token to deposit and the amount of wrapped native token to send
142 | | */
143 | * | function depositAndSendWrappedNativeToken(
144 | | DataStore dataStore,
145 | | address receiver,
146 | | uint256 amount
147 | * | ) internal {
148 | * | if (amount == 0) { return; }
149 | * | AccountUtils.validateReceiver(receiver);
150 | |
151 | * | address _wnt = wnt(dataStore);
152 | * | IWNT(_wnt).deposit{value: amount}();
153 | |
154 | * | transfer(
155 | * | dataStore,
156 | * | _wnt,
157 | * | receiver,
158 | * | amount
159 | | );
160 | | }
161 | |
162 | | /**
163 | | * @dev Withdraws the specified amount of wrapped native token and sends the
164 | | * corresponding amount of native token to the specified receiver address.
165 | | *
166 | | * limit the amount of gas forwarded so that a user cannot intentionally
167 | | * construct a token call that would consume all gas and prevent necessary
168 | | * actions like request cancellation from being executed
169 | | *
170 | | * @param dataStore the data store to use for storing and retrieving data
171 | | * @param _wnt the address of the WNT contract to withdraw the wrapped native token from
172 | | * @param receiver the address of the recipient of the native token transfer
173 | | * @param amount the amount of wrapped native token to withdraw and the amount of native token to send
174 | | */
175 | | function withdrawAndSendNativeToken(
176 | | DataStore dataStore,
177 | | address _wnt,
178 | | address receiver,
179 | | uint256 amount
180 | | ) internal {
181 | | if (amount == 0) { return; }
182 | | AccountUtils.validateReceiver(receiver);
183 | |
184 | | IWNT(_wnt).withdraw(amount);
185 | |
186 | | uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);
187 | |
188 | | bool success;
189 | | // use an assembly call to avoid loading large data into memory
190 | | // input mem[in…(in+insize)]
191 | | // output area mem[out…(out+outsize))]
192 | | assembly {
193 | | success := call(
194 | | gasLimit, // gas limit
195 | | receiver, // receiver
196 | | amount, // value
197 | | 0, // in
198 | | 0, // insize
199 | | 0, // out
200 | | 0 // outsize
201 | | )
202 | | }
203 | |
204 | | if (success) { return; }
205 | |
206 | | // if the transfer failed, re-wrap the token and send it to the receiver
207 | | depositAndSendWrappedNativeToken(
208 | | dataStore,
209 | | receiver,
210 | | amount
211 | | );
212 | | }
213 | |
214 | | /**
215 | | * @dev Transfers the specified amount of ERC20 token to the specified receiver
216 | | * address, with a gas limit to prevent the transfer from consuming all available gas.
217 | | * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol
218 | | *
219 | | * @param token the ERC20 contract to transfer the tokens from
220 | | * @param to the address of the recipient of the token transfer
221 | | * @param amount the amount of tokens to transfer
222 | | * @param gasLimit the maximum amount of gas that the token transfer can consume
223 | | * @return a tuple containing a boolean indicating the success or failure of the
224 | | * token transfer, and a bytes value containing the return data from the token transfer
225 | | */
226 | * | function nonRevertingTransferWithGasLimit(
227 | | IERC20 token,
228 | | address to,
229 | | uint256 amount,
230 | | uint256 gasLimit
231 | * | ) internal returns (bool, bytes memory) {
232 | * | bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);
233 | * | (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);
234 | |
235 | * | if (success) {
236 | * | if (returndata.length == 0) {
237 | | // only check isContract if the call was successful and the return data is empty
238 | | // otherwise we already know that it was a contract
239 | | if (!address(token).isContract()) {
240 | | return (false, "Call to non-contract");
241 | | }
242 | | }
243 | |
244 | | // some tokens do not revert on a failed transfer, they will return a boolean instead
245 | | // validate that the returned boolean is true, otherwise indicate that the token transfer failed
246 | * | if (returndata.length > 0 && !abi.decode(returndata, (bool))) {
247 | | return (false, returndata);
248 | | }
249 | |
250 | | // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails
251 | | // for these tokens, if success is true then the transfer should have completed
252 | * | return (true, returndata);
253 | | }
254 | |
255 | | return (false, returndata);
256 | | }
257 | | }
258 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/AccountUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../error/Errors.sol";
6 | |
7 | * | library AccountUtils {
8 | * | function validateAccount(address account) internal pure {
9 | * | if (account == address(0)) {
10 | | revert Errors.EmptyAccount();
11 | | }
12 | | }
13 | |
14 | * | function validateReceiver(address receiver) internal pure {
15 | * | if (receiver == address(0)) {
16 | | revert Errors.EmptyReceiver();
17 | | }
18 | | }
19 | | }
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Array.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
6 | | import "../error/Errors.sol";
7 | |
8 | | /**
9 | | * @title Array
10 | | * @dev Library for array functions
11 | | */
12 | * | library Array {
13 | | using SafeCast for int256;
14 | |
15 | | /**
16 | | * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0.
17 | | *
18 | | * @param arr the array to get the value from
19 | | * @param index the index of the element in the array
20 | | * @return the value of the element at the specified index in the array
21 | | */
22 | | function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {
23 | | if (index < arr.length) {
24 | | return arr[index];
25 | | }
26 | |
27 | | return bytes32(0);
28 | | }
29 | |
30 | | /**
31 | | * @dev Determines whether all of the elements in the given array are equal to the specified value.
32 | | *
33 | | * @param arr the array to check the elements of
34 | | * @param value the value to compare the elements of the array to
35 | | * @return true if all of the elements in the array are equal to the specified value, false otherwise
36 | | */
37 | | function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
38 | | for (uint256 i; i < arr.length; i++) {
39 | | if (arr[i] != value) {
40 | | return false;
41 | | }
42 | | }
43 | |
44 | | return true;
45 | | }
46 | |
47 | | /**
48 | | * @dev Determines whether all of the elements in the given array are greater than the specified value.
49 | | *
50 | | * @param arr the array to check the elements of
51 | | * @param value the value to compare the elements of the array to
52 | | * @return true if all of the elements in the array are greater than the specified value, false otherwise
53 | | */
54 | | function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
55 | | for (uint256 i; i < arr.length; i++) {
56 | | if (arr[i] <= value) {
57 | | return false;
58 | | }
59 | | }
60 | |
61 | | return true;
62 | | }
63 | |
64 | | /**
65 | | * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value.
66 | | *
67 | | * @param arr the array to check the elements of
68 | | * @param value the value to compare the elements of the array to
69 | | * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise
70 | | */
71 | | function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
72 | | for (uint256 i; i < arr.length; i++) {
73 | | if (arr[i] < value) {
74 | | return false;
75 | | }
76 | | }
77 | |
78 | | return true;
79 | | }
80 | |
81 | | /**
82 | | * @dev Determines whether all of the elements in the given array are less than the specified value.
83 | | *
84 | | * @param arr the array to check the elements of
85 | | * @param value the value to compare the elements of the array to
86 | | * @return true if all of the elements in the array are less than the specified value, false otherwise
87 | | */
88 | | function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
89 | | for (uint256 i; i < arr.length; i++) {
90 | | if (arr[i] >= value) {
91 | | return false;
92 | | }
93 | | }
94 | |
95 | | return true;
96 | | }
97 | |
98 | | /**
99 | | * @dev Determines whether all of the elements in the given array are less than or equal to the specified value.
100 | | *
101 | | * @param arr the array to check the elements of
102 | | * @param value the value to compare the elements of the array to
103 | | * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise
104 | | */
105 | | function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
106 | | for (uint256 i; i < arr.length; i++) {
107 | | if (arr[i] > value) {
108 | | return false;
109 | | }
110 | | }
111 | |
112 | | return true;
113 | | }
114 | |
115 | | /**
116 | | * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements.
117 | | *
118 | | * @param arr the array to get the median value from
119 | | * @return the median value of the elements in the given array
120 | | */
121 | | function getMedian(uint256[] memory arr) internal pure returns (uint256) {
122 | | if (arr.length % 2 == 1) {
123 | | return arr[arr.length / 2];
124 | | }
125 | |
126 | | return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;
127 | | }
128 | |
129 | | /**
130 | | * @dev Gets the uncompacted value at the specified index in the given array of compacted values.
131 | | *
132 | | * @param compactedValues the array of compacted values to get the uncompacted value from
133 | | * @param index the index of the uncompacted value in the array
134 | | * @param compactedValueBitLength the length of each compacted value, in bits
135 | | * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value
136 | | * @return the uncompacted value at the specified index in the array of compacted values
137 | | */
138 | | function getUncompactedValue(
139 | | uint256[] memory compactedValues,
140 | | uint256 index,
141 | | uint256 compactedValueBitLength,
142 | | uint256 bitmask,
143 | | string memory label
144 | | ) internal pure returns (uint256) {
145 | | uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;
146 | |
147 | | uint256 slotIndex = index / compactedValuesPerSlot;
148 | | if (slotIndex >= compactedValues.length) {
149 | | revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);
150 | | }
151 | |
152 | | uint256 slotBits = compactedValues[slotIndex];
153 | | uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;
154 | |
155 | | uint256 value = (slotBits >> offset) & bitmask;
156 | |
157 | | return value;
158 | | }
159 | | }
160 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/BasicMulticall.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../error/ErrorUtils.sol";
6 | |
7 | | /**
8 | | * @title BasicMulticall
9 | | */
10 | | abstract contract BasicMulticall {
11 | | /**
12 | | * @dev Receives and executes a batch of function calls on this contract.
13 | | */
14 | | function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
15 | | results = new bytes[](data.length);
16 | |
17 | | for (uint256 i; i < data.length; i++) {
18 | | (bool success, bytes memory result) = address(this).delegatecall(data[i]);
19 | |
20 | | if (!success) {
21 | | ErrorUtils.revertWithParsedMessage(result);
22 | | }
23 | |
24 | | results[i] = result;
25 | | }
26 | |
27 | | return results;
28 | | }
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Bits.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @title Bits
7 | | * @dev Library for bit values
8 | | */
9 | * | library Bits {
10 | | // @dev uint256(~0) is 256 bits of 1s
11 | | // @dev shift the 1s by (256 - 8) to get (256 - 8) 0s followed by 8 1s
12 | | uint256 constant internal BITMASK_8 = ~uint256(0) >> (256 - 8);
13 | | // @dev shift the 1s by (256 - 16) to get (256 - 16) 0s followed by 16 1s
14 | | uint256 constant internal BITMASK_16 = ~uint256(0) >> (256 - 16);
15 | | // @dev shift the 1s by (256 - 32) to get (256 - 32) 0s followed by 32 1s
16 | | uint256 constant internal BITMASK_32 = ~uint256(0) >> (256 - 32);
17 | | // @dev shift the 1s by (256 - 64) to get (256 - 64) 0s followed by 64 1s
18 | | uint256 constant internal BITMASK_64 = ~uint256(0) >> (256 - 64);
19 | | }
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Calc.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
7 | |
8 | | /**
9 | | * @title Calc
10 | | * @dev Library for math functions
11 | | */
12 | * | library Calc {
13 | | using SignedMath for int256;
14 | | using SafeCast for uint256;
15 | |
16 | | // this method assumes that min is less than max
17 | | function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {
18 | | uint256 magnitude = value.abs();
19 | |
20 | | if (magnitude < min) {
21 | | magnitude = min;
22 | | }
23 | |
24 | | if (magnitude > max) {
25 | | magnitude = max;
26 | | }
27 | |
28 | | int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();
29 | |
30 | | return magnitude.toInt256() * sign;
31 | | }
32 | |
33 | | /**
34 | | * @dev Calculates the result of dividing the first number by the second number,
35 | | * rounded up to the nearest integer.
36 | | *
37 | | * @param a the dividend
38 | | * @param b the divisor
39 | | * @return the result of dividing the first number by the second number, rounded up to the nearest integer
40 | | */
41 | * | function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {
42 | * | return (a + b - 1) / b;
43 | | }
44 | |
45 | | /**
46 | | * Calculates the result of dividing the first number by the second number,
47 | | * rounded up to the nearest integer.
48 | | * The rounding is purely on the magnitude of a, if a is negative the result
49 | | * is a larger magnitude negative
50 | | *
51 | | * @param a the dividend
52 | | * @param b the divisor
53 | | * @return the result of dividing the first number by the second number, rounded up to the nearest integer
54 | | */
55 | * | function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {
56 | * | if (a < 0) {
57 | * | return (a - b.toInt256() + 1) / b.toInt256();
58 | | }
59 | |
60 | * | return (a + b.toInt256() - 1) / b.toInt256();
61 | | }
62 | |
63 | | /**
64 | | * Adds two numbers together and return a uint256 value, treating the second number as a signed integer.
65 | | *
66 | | * @param a the first number
67 | | * @param b the second number
68 | | * @return the result of adding the two numbers together
69 | | */
70 | * | function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {
71 | * | if (b > 0) {
72 | * | return a + b.abs();
73 | | }
74 | |
75 | * | return a - b.abs();
76 | | }
77 | |
78 | | /**
79 | | * Adds two numbers together and return an int256 value, treating the second number as a signed integer.
80 | | *
81 | | * @param a the first number
82 | | * @param b the second number
83 | | * @return the result of adding the two numbers together
84 | | */
85 | | function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {
86 | | return a.toInt256() + b;
87 | | }
88 | |
89 | | /**
90 | | * @dev Calculates the absolute difference between two numbers.
91 | | *
92 | | * @param a the first number
93 | | * @param b the second number
94 | | * @return the absolute difference between the two numbers
95 | | */
96 | * | function diff(uint256 a, uint256 b) internal pure returns (uint256) {
97 | * | return a > b ? a - b : b - a;
98 | | }
99 | |
100 | | /**
101 | | * Adds two numbers together, the result is bounded to prevent overflows.
102 | | *
103 | | * @param a the first number
104 | | * @param b the second number
105 | | * @return the result of adding the two numbers together
106 | | */
107 | | function boundedAdd(int256 a, int256 b) internal pure returns (int256) {
108 | | // if either a or b is zero or if the signs are different there should not be any overflows
109 | | if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {
110 | | return a + b;
111 | | }
112 | |
113 | | // if adding `b` to `a` would result in a value less than the min int256 value
114 | | // then return the min int256 value
115 | | if (a < 0 && b <= type(int256).min - a) {
116 | | return type(int256).min;
117 | | }
118 | |
119 | | // if adding `b` to `a` would result in a value more than the max int256 value
120 | | // then return the max int256 value
121 | | if (a > 0 && b >= type(int256).max - a) {
122 | | return type(int256).max;
123 | | }
124 | |
125 | | return a + b;
126 | | }
127 | |
128 | | /**
129 | | * Returns a - b, the result is bounded to prevent overflows.
130 | | * Note that this will revert if b is type(int256).min because of the usage of "-b".
131 | | *
132 | | * @param a the first number
133 | | * @param b the second number
134 | | * @return the bounded result of a - b
135 | | */
136 | | function boundedSub(int256 a, int256 b) internal pure returns (int256) {
137 | | // if either a or b is zero or the signs are the same there should not be any overflow
138 | | if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {
139 | | return a - b;
140 | | }
141 | |
142 | | // if adding `-b` to `a` would result in a value greater than the max int256 value
143 | | // then return the max int256 value
144 | | if (a > 0 && -b >= type(int256).max - a) {
145 | | return type(int256).max;
146 | | }
147 | |
148 | | // if subtracting `b` from `a` would result in a value less than the min int256 value
149 | | // then return the min int256 value
150 | | if (a < 0 && -b <= type(int256).min - a) {
151 | | return type(int256).min;
152 | | }
153 | |
154 | | return a - b;
155 | | }
156 | |
157 | |
158 | | /**
159 | | * Converts the given unsigned integer to a signed integer, using the given
160 | | * flag to determine whether the result should be positive or negative.
161 | | *
162 | | * @param a the unsigned integer to convert
163 | | * @param isPositive whether the result should be positive (if true) or negative (if false)
164 | | * @return the signed integer representation of the given unsigned integer
165 | | */
166 | * | function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {
167 | * | if (isPositive) {
168 | * | return a.toInt256();
169 | | } else {
170 | * | return -a.toInt256();
171 | | }
172 | | }
173 | | }
174 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Cast.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @title Cast
7 | | * @dev Library for casting functions
8 | | */
9 | * | library Cast {
10 | * | function toBytes32(address value) internal pure returns (bytes32) {
11 | * | return bytes32(uint256(uint160(value)));
12 | | }
13 | | }
14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/EnumerableValues.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
6 | |
7 | | /**
8 | | * @title EnumerableValues
9 | | * @dev Library to extend the EnumerableSet library with functions to get
10 | | * valuesAt for a range
11 | | */
12 | * | library EnumerableValues {
13 | | using EnumerableSet for EnumerableSet.Bytes32Set;
14 | | using EnumerableSet for EnumerableSet.AddressSet;
15 | | using EnumerableSet for EnumerableSet.UintSet;
16 | |
17 | | /**
18 | | * Returns an array of bytes32 values from the given set, starting at the given
19 | | * start index and ending before the given end index.
20 | | *
21 | | * @param set The set to get the values from.
22 | | * @param start The starting index.
23 | | * @param end The ending index.
24 | | * @return An array of bytes32 values.
25 | | */
26 | * | function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
27 | * | uint256 max = set.length();
28 | * | if (end > max) { end = max; }
29 | |
30 | * | bytes32[] memory items = new bytes32[](end - start);
31 | * | for (uint256 i = start; i < end; i++) {
32 | * | items[i - start] = set.at(i);
33 | | }
34 | |
35 | * | return items;
36 | | }
37 | |
38 | |
39 | | /**
40 | | * Returns an array of address values from the given set, starting at the given
41 | | * start index and ending before the given end index.
42 | | *
43 | | * @param set The set to get the values from.
44 | | * @param start The starting index.
45 | | * @param end The ending index.
46 | | * @return An array of address values.
47 | | */
48 | | function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {
49 | | uint256 max = set.length();
50 | | if (end > max) { end = max; }
51 | |
52 | | address[] memory items = new address[](end - start);
53 | | for (uint256 i = start; i < end; i++) {
54 | | items[i - start] = set.at(i);
55 | | }
56 | |
57 | | return items;
58 | | }
59 | |
60 | |
61 | | /**
62 | | * Returns an array of uint256 values from the given set, starting at the given
63 | | * start index and ending before the given end index, the item at the end index will not be returned.
64 | | *
65 | | * @param set The set to get the values from.
66 | | * @param start The starting index (inclusive, item at the start index will be returned).
67 | | * @param end The ending index (exclusive, item at the end index will not be returned).
68 | | * @return An array of uint256 values.
69 | | */
70 | | function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {
71 | | if (start >= set.length()) {
72 | | return new uint256[](0);
73 | | }
74 | |
75 | | uint256 max = set.length();
76 | | if (end > max) { end = max; }
77 | |
78 | | uint256[] memory items = new uint256[](end - start);
79 | | for (uint256 i = start; i < end; i++) {
80 | | items[i - start] = set.at(i);
81 | | }
82 | |
83 | | return items;
84 | | }
85 | | }
86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/GlobalReentrancyGuard.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | abstract contract GlobalReentrancyGuard {
9 | | // Booleans are more expensive than uint256 or any type that takes up a full
10 | | // word because each write operation emits an extra SLOAD to first read the
11 | | // slot's contents, replace the bits taken up by the boolean, and then write
12 | | // back. This is the compiler's defense against contract upgrades and
13 | | // pointer aliasing, and it cannot be disabled.
14 | * | uint256 private constant NOT_ENTERED = 0;
15 | * | uint256 private constant ENTERED = 1;
16 | |
17 | | DataStore public immutable dataStore;
18 | |
19 | | constructor(DataStore _dataStore) {
20 | | dataStore = _dataStore;
21 | | }
22 | |
23 | | modifier globalNonReentrant() {
24 | * | _globalNonReentrantBefore();
25 | | _;
26 | * | _globalNonReentrantAfter();
27 | | }
28 | |
29 | * | function _globalNonReentrantBefore() private {
30 | * | uint256 status = dataStore.getUint(Keys.REENTRANCY_GUARD_STATUS);
31 | |
32 | * | require(status == NOT_ENTERED, "ReentrancyGuard: reentrant call");
33 | |
34 | * | dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, ENTERED);
35 | | }
36 | |
37 | * | function _globalNonReentrantAfter() private {
38 | * | dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, NOT_ENTERED);
39 | | }
40 | | }
41 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/PayableMulticall.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../error/ErrorUtils.sol";
6 | |
7 | | /**
8 | | * @title PayableMulticall
9 | | * @dev Contract to help call multiple functions in a single transaction
10 | | * all function calls will have the original sender as the msg.sender value
11 | | * IMPORTANT: in the multicall, msg.value will be the same for each delegatecall
12 | | * extra care should be taken if msg.value is used in any of the functions of the inheriting contract
13 | | */
14 | | abstract contract PayableMulticall {
15 | | /**
16 | | * @dev Receives and executes a batch of function calls on this contract.
17 | | */
18 | | function multicall(bytes[] calldata data) external payable virtual returns (bytes[] memory results) {
19 | | results = new bytes[](data.length);
20 | |
21 | | for (uint256 i; i < data.length; i++) {
22 | | (bool success, bytes memory result) = address(this).delegatecall(data[i]);
23 | |
24 | | if (!success) {
25 | | ErrorUtils.revertWithParsedMessage(result);
26 | | }
27 | |
28 | | results[i] = result;
29 | | }
30 | |
31 | | return results;
32 | | }
33 | | }
34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Precision.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | // there is a known issue with prb-math v3.x releases
6 | | // https://github.com/PaulRBerg/prb-math/issues/178
7 | | // due to this, either prb-math v2.x or v4.x versions should be used instead
8 | | import "prb-math/contracts/PRBMathUD60x18.sol";
9 | |
10 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
11 | | import "@openzeppelin/contracts/utils/math/SafeMath.sol";
12 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol";
13 | | import "@openzeppelin/contracts/utils/math/Math.sol";
14 | |
15 | | import "./Calc.sol";
16 | |
17 | | /**
18 | | * @title Precision
19 | | * @dev Library for precision values and conversions
20 | | */
21 | * | library Precision {
22 | | using SafeCast for uint256;
23 | | using SignedMath for int256;
24 | |
25 | * | uint256 internal constant FLOAT_PRECISION = 10 ** 30;
26 | * | uint256 internal constant FLOAT_PRECISION_SQRT = 10 ** 15;
27 | |
28 | | uint256 internal constant WEI_PRECISION = 10 ** 18;
29 | * | uint256 internal constant BASIS_POINTS_DIVISOR = 10000;
30 | |
31 | * | uint256 internal constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;
32 | |
33 | | /**
34 | | * Applies the given factor to the given value and returns the result.
35 | | *
36 | | * @param value The value to apply the factor to.
37 | | * @param factor The factor to apply.
38 | | * @return The result of applying the factor to the value.
39 | | */
40 | * | function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {
41 | * | return mulDiv(value, factor, FLOAT_PRECISION);
42 | | }
43 | |
44 | | /**
45 | | * Applies the given factor to the given value and returns the result.
46 | | *
47 | | * @param value The value to apply the factor to.
48 | | * @param factor The factor to apply.
49 | | * @return The result of applying the factor to the value.
50 | | */
51 | | function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {
52 | | return mulDiv(value, factor, FLOAT_PRECISION);
53 | | }
54 | |
55 | | function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {
56 | | return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);
57 | | }
58 | |
59 | * | function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {
60 | * | return Math.mulDiv(value, numerator, denominator);
61 | | }
62 | |
63 | * | function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {
64 | * | return mulDiv(numerator, value, denominator);
65 | | }
66 | |
67 | * | function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {
68 | * | uint256 result = mulDiv(value, numerator.abs(), denominator);
69 | * | return numerator > 0 ? result.toInt256() : -result.toInt256();
70 | | }
71 | |
72 | | function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {
73 | | uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);
74 | | return numerator > 0 ? result.toInt256() : -result.toInt256();
75 | | }
76 | |
77 | * | function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {
78 | * | if (roundUpMagnitude) {
79 | * | return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);
80 | | }
81 | |
82 | * | return Math.mulDiv(value, numerator, denominator);
83 | | }
84 | |
85 | * | function applyExponentFactor(
86 | | uint256 floatValue,
87 | | uint256 exponentFactor
88 | * | ) internal pure returns (uint256) {
89 | | // `PRBMathUD60x18.pow` doesn't work for `x` less than one
90 | * | if (floatValue < FLOAT_PRECISION) {
91 | * | return 0;
92 | | }
93 | |
94 | * | if (exponentFactor == FLOAT_PRECISION) {
95 | * | return floatValue;
96 | | }
97 | |
98 | | // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18
99 | | // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals
100 | * | uint256 weiValue = PRBMathUD60x18.pow(
101 | * | floatToWei(floatValue),
102 | * | floatToWei(exponentFactor)
103 | | );
104 | |
105 | * | return weiToFloat(weiValue);
106 | | }
107 | |
108 | * | function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {
109 | * | if (value == 0) { return 0; }
110 | |
111 | * | if (roundUpMagnitude) {
112 | | return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);
113 | | }
114 | |
115 | * | return Math.mulDiv(value, FLOAT_PRECISION, divisor);
116 | | }
117 | |
118 | * | function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {
119 | * | return toFactor(value, divisor, false);
120 | | }
121 | |
122 | * | function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {
123 | * | uint256 result = toFactor(value.abs(), divisor);
124 | * | return value > 0 ? result.toInt256() : -result.toInt256();
125 | | }
126 | |
127 | | /**
128 | | * Converts the given value from float to wei.
129 | | *
130 | | * @param value The value to convert.
131 | | * @return The converted value in wei.
132 | | */
133 | * | function floatToWei(uint256 value) internal pure returns (uint256) {
134 | * | return value / FLOAT_TO_WEI_DIVISOR;
135 | | }
136 | |
137 | | /**
138 | | * Converts the given value from wei to float.
139 | | *
140 | | * @param value The value to convert.
141 | | * @return The converted value in float.
142 | | */
143 | * | function weiToFloat(uint256 value) internal pure returns (uint256) {
144 | * | return value * FLOAT_TO_WEI_DIVISOR;
145 | | }
146 | |
147 | | /**
148 | | * Converts the given number of basis points to float.
149 | | *
150 | | * @param basisPoints The number of basis points to convert.
151 | | * @return The converted value in float.
152 | | */
153 | * | function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {
154 | * | return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;
155 | | }
156 | | }
157 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Printer.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
6 | |
7 | | /**
8 | | * @title Printer
9 | | * @dev Library for console functions
10 | | */
11 | * | library Printer {
12 | | using SafeCast for int256;
13 | |
14 | | function log(string memory str) internal pure {
15 | | }
16 | |
17 | | function log(string memory label, int256 value) internal pure {
18 | | if (value < 0) {
19 | | } else {
20 | | }
21 | | }
22 | | }
23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Uint256Mask.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../error/Errors.sol";
6 | |
7 | * | library Uint256Mask {
8 | | struct Mask {
9 | | uint256 bits;
10 | | }
11 | |
12 | | function validateUniqueAndSetIndex(
13 | | Mask memory mask,
14 | | uint256 index,
15 | | string memory label
16 | | ) internal pure {
17 | | if (index >= 256) {
18 | | revert Errors.MaskIndexOutOfBounds(index, label);
19 | | }
20 | |
21 | | uint256 bit = 1 << index;
22 | |
23 | | if (mask.bits & bit != 0) {
24 | | revert Errors.DuplicatedIndex(index, label);
25 | | }
26 | |
27 | | mask.bits = mask.bits | bit;
28 | | }
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/v1/IRouterV1.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | interface IRouterV1 {
6 | | function swap(address[] memory _path, uint256 _amountIn, uint256 _minOut, address _receiver) external;
7 | | }
8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/v1/IVaultV1.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | interface IVaultV1 {
6 | | function allWhitelistedTokensLength() external view returns (uint256);
7 | | function allWhitelistedTokens(uint256) external view returns (address);
8 | | function withdrawFees(address _token, address _receiver) external returns (uint256);
9 | | }
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/ExecuteWithdrawalUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../adl/AdlUtils.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | |
9 | | import "./WithdrawalVault.sol";
10 | | import "./WithdrawalStoreUtils.sol";
11 | | import "./WithdrawalEventUtils.sol";
12 | |
13 | | import "../nonce/NonceUtils.sol";
14 | | import "../pricing/SwapPricingUtils.sol";
15 | | import "../oracle/Oracle.sol";
16 | | import "../oracle/OracleUtils.sol";
17 | |
18 | | import "../gas/GasUtils.sol";
19 | | import "../callback/CallbackUtils.sol";
20 | |
21 | | import "../utils/Array.sol";
22 | | import "../utils/AccountUtils.sol";
23 | |
24 | * | library ExecuteWithdrawalUtils {
25 | | using SafeCast for uint256;
26 | | using SafeCast for int256;
27 | | using Array for uint256[];
28 | | using Price for Price.Props;
29 | | using Withdrawal for Withdrawal.Props;
30 | |
31 | | using EventUtils for EventUtils.AddressItems;
32 | | using EventUtils for EventUtils.UintItems;
33 | | using EventUtils for EventUtils.IntItems;
34 | | using EventUtils for EventUtils.BoolItems;
35 | | using EventUtils for EventUtils.Bytes32Items;
36 | | using EventUtils for EventUtils.BytesItems;
37 | | using EventUtils for EventUtils.StringItems;
38 | |
39 | | struct ExecuteWithdrawalParams {
40 | | DataStore dataStore;
41 | | EventEmitter eventEmitter;
42 | | WithdrawalVault withdrawalVault;
43 | | Oracle oracle;
44 | | bytes32 key;
45 | | address keeper;
46 | | uint256 startingGas;
47 | | ISwapPricingUtils.SwapPricingType swapPricingType;
48 | | }
49 | |
50 | | struct ExecuteWithdrawalCache {
51 | | uint256 requestExpirationTime;
52 | | uint256 maxOracleTimestamp;
53 | | uint256 marketTokensBalance;
54 | | Market.Props market;
55 | | MarketUtils.MarketPrices prices;
56 | | }
57 | |
58 | | struct _ExecuteWithdrawalCache {
59 | | uint256 longTokenOutputAmount;
60 | | uint256 shortTokenOutputAmount;
61 | | SwapPricingUtils.SwapFees longTokenFees;
62 | | SwapPricingUtils.SwapFees shortTokenFees;
63 | | uint256 longTokenPoolAmountDelta;
64 | | uint256 shortTokenPoolAmountDelta;
65 | | }
66 | |
67 | | struct ExecuteWithdrawalResult {
68 | | address outputToken;
69 | | uint256 outputAmount;
70 | | address secondaryOutputToken;
71 | | uint256 secondaryOutputAmount;
72 | | }
73 | |
74 | | struct SwapCache {
75 | | Market.Props[] swapPathMarkets;
76 | | SwapUtils.SwapParams swapParams;
77 | | address outputToken;
78 | | uint256 outputAmount;
79 | | }
80 | |
81 | | /**
82 | | * Executes a withdrawal on the market.
83 | | *
84 | | * @param params The parameters for executing the withdrawal.
85 | | */
86 | * | function executeWithdrawal(ExecuteWithdrawalParams memory params, Withdrawal.Props memory withdrawal) internal {
87 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
88 | * | params.startingGas -= gasleft() / 63;
89 | |
90 | * | WithdrawalStoreUtils.remove(params.dataStore, params.key, withdrawal.account());
91 | |
92 | * | if (withdrawal.account() == address(0)) {
93 | | revert Errors.EmptyWithdrawal();
94 | | }
95 | * | if (withdrawal.marketTokenAmount() == 0) {
96 | | revert Errors.EmptyWithdrawalAmount();
97 | | }
98 | |
99 | * | if (params.oracle.minTimestamp() < withdrawal.updatedAtTime()) {
100 | | revert Errors.OracleTimestampsAreSmallerThanRequired(
101 | | params.oracle.minTimestamp(),
102 | | withdrawal.updatedAtTime()
103 | | );
104 | | }
105 | |
106 | * | ExecuteWithdrawalCache memory cache;
107 | |
108 | * | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME);
109 | * | cache.maxOracleTimestamp = params.oracle.maxTimestamp();
110 | |
111 | * | if (cache.maxOracleTimestamp > withdrawal.updatedAtTime() + cache.requestExpirationTime) {
112 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime(
113 | * | cache.maxOracleTimestamp,
114 | * | withdrawal.updatedAtTime(),
115 | * | cache.requestExpirationTime
116 | | );
117 | | }
118 | |
119 | * | MarketUtils.distributePositionImpactPool(
120 | * | params.dataStore,
121 | * | params.eventEmitter,
122 | * | withdrawal.market()
123 | | );
124 | |
125 | * | cache.market = MarketUtils.getEnabledMarket(params.dataStore, withdrawal.market());
126 | * | cache.prices = MarketUtils.getMarketPrices(
127 | * | params.oracle,
128 | * | cache.market
129 | | );
130 | |
131 | * | PositionUtils.updateFundingAndBorrowingState(
132 | * | params.dataStore,
133 | * | params.eventEmitter,
134 | * | cache.market,
135 | * | cache.prices
136 | | );
137 | |
138 | * | cache.marketTokensBalance = MarketToken(payable(withdrawal.market())).balanceOf(address(params.withdrawalVault));
139 | * | if (cache.marketTokensBalance < withdrawal.marketTokenAmount()) {
140 | | revert Errors.InsufficientMarketTokens(cache.marketTokensBalance, withdrawal.marketTokenAmount());
141 | | }
142 | |
143 | * | ExecuteWithdrawalResult memory result = _executeWithdrawal(
144 | * | params,
145 | * | withdrawal,
146 | * | cache.market,
147 | * | cache.prices
148 | | );
149 | |
150 | * | WithdrawalEventUtils.emitWithdrawalExecuted(
151 | * | params.eventEmitter,
152 | * | params.key,
153 | * | withdrawal.account(),
154 | * | params.swapPricingType
155 | | );
156 | |
157 | * | EventUtils.EventLogData memory eventData;
158 | * | eventData.addressItems.initItems(2);
159 | * | eventData.addressItems.setItem(0, "outputToken", result.outputToken);
160 | * | eventData.addressItems.setItem(1, "secondaryOutputToken", result.secondaryOutputToken);
161 | * | eventData.uintItems.initItems(2);
162 | * | eventData.uintItems.setItem(0, "outputAmount", result.outputAmount);
163 | * | eventData.uintItems.setItem(1, "secondaryOutputAmount", result.secondaryOutputAmount);
164 | * | CallbackUtils.afterWithdrawalExecution(params.key, withdrawal, eventData);
165 | |
166 | * | GasUtils.payExecutionFee(
167 | * | params.dataStore,
168 | * | params.eventEmitter,
169 | * | params.withdrawalVault,
170 | * | params.key,
171 | * | withdrawal.callbackContract(),
172 | * | withdrawal.executionFee(),
173 | * | params.startingGas,
174 | * | GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length),
175 | * | params.keeper,
176 | * | withdrawal.receiver()
177 | | );
178 | | }
179 | |
180 | | /**
181 | | * @dev executes a withdrawal.
182 | | * @param params ExecuteWithdrawalParams.
183 | | * @param withdrawal The withdrawal to execute.
184 | | */
185 | * | function _executeWithdrawal(
186 | | ExecuteWithdrawalParams memory params,
187 | | Withdrawal.Props memory withdrawal,
188 | | Market.Props memory market,
189 | | MarketUtils.MarketPrices memory prices
190 | * | ) internal returns (ExecuteWithdrawalResult memory) {
191 | * | _ExecuteWithdrawalCache memory cache;
192 | |
193 | * | (cache.longTokenOutputAmount, cache.shortTokenOutputAmount) = _getOutputAmounts(params, market, prices, withdrawal.marketTokenAmount());
194 | |
195 | * | cache.longTokenFees = SwapPricingUtils.getSwapFees(
196 | * | params.dataStore,
197 | * | market.marketToken,
198 | * | cache.longTokenOutputAmount,
199 | * | false, // forPositiveImpact
200 | * | withdrawal.uiFeeReceiver(),
201 | * | params.swapPricingType
202 | | );
203 | |
204 | * | FeeUtils.incrementClaimableFeeAmount(
205 | * | params.dataStore,
206 | * | params.eventEmitter,
207 | * | market.marketToken,
208 | * | market.longToken,
209 | * | cache.longTokenFees.feeReceiverAmount,
210 | | Keys.WITHDRAWAL_FEE_TYPE
211 | | );
212 | |
213 | * | FeeUtils.incrementClaimableUiFeeAmount(
214 | * | params.dataStore,
215 | * | params.eventEmitter,
216 | * | withdrawal.uiFeeReceiver(),
217 | * | market.marketToken,
218 | * | market.longToken,
219 | * | cache.longTokenFees.uiFeeAmount,
220 | | Keys.UI_WITHDRAWAL_FEE_TYPE
221 | | );
222 | |
223 | * | cache.shortTokenFees = SwapPricingUtils.getSwapFees(
224 | * | params.dataStore,
225 | * | market.marketToken,
226 | * | cache.shortTokenOutputAmount,
227 | * | false, // forPositiveImpact
228 | * | withdrawal.uiFeeReceiver(),
229 | * | params.swapPricingType
230 | | );
231 | |
232 | * | FeeUtils.incrementClaimableFeeAmount(
233 | * | params.dataStore,
234 | * | params.eventEmitter,
235 | * | market.marketToken,
236 | * | market.shortToken,
237 | * | cache.shortTokenFees.feeReceiverAmount,
238 | | Keys.WITHDRAWAL_FEE_TYPE
239 | | );
240 | |
241 | * | FeeUtils.incrementClaimableUiFeeAmount(
242 | * | params.dataStore,
243 | * | params.eventEmitter,
244 | * | withdrawal.uiFeeReceiver(),
245 | * | market.marketToken,
246 | * | market.shortToken,
247 | * | cache.shortTokenFees.uiFeeAmount,
248 | | Keys.UI_WITHDRAWAL_FEE_TYPE
249 | | );
250 | |
251 | | // the pool will be reduced by the outputAmount minus the fees for the pool
252 | * | cache.longTokenPoolAmountDelta = cache.longTokenOutputAmount - cache.longTokenFees.feeAmountForPool;
253 | * | cache.longTokenOutputAmount = cache.longTokenFees.amountAfterFees;
254 | |
255 | * | cache.shortTokenPoolAmountDelta = cache.shortTokenOutputAmount - cache.shortTokenFees.feeAmountForPool;
256 | * | cache.shortTokenOutputAmount = cache.shortTokenFees.amountAfterFees;
257 | |
258 | | // it is rare but possible for withdrawals to be blocked because pending borrowing fees
259 | | // have not yet been deducted from position collateral and credited to the poolAmount value
260 | * | MarketUtils.applyDeltaToPoolAmount(
261 | * | params.dataStore,
262 | * | params.eventEmitter,
263 | * | market,
264 | * | market.longToken,
265 | * | -cache.longTokenPoolAmountDelta.toInt256()
266 | | );
267 | |
268 | * | MarketUtils.applyDeltaToPoolAmount(
269 | * | params.dataStore,
270 | * | params.eventEmitter,
271 | * | market,
272 | * | market.shortToken,
273 | * | -cache.shortTokenPoolAmountDelta.toInt256()
274 | | );
275 | |
276 | * | MarketUtils.validateReserve(
277 | * | params.dataStore,
278 | * | market,
279 | * | prices,
280 | * | true
281 | | );
282 | |
283 | * | MarketUtils.validateReserve(
284 | * | params.dataStore,
285 | * | market,
286 | * | prices,
287 | * | false
288 | | );
289 | |
290 | * | MarketUtils.validateMaxPnl(
291 | * | params.dataStore,
292 | * | market,
293 | * | prices,
294 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
295 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS
296 | | );
297 | |
298 | * | MarketToken(payable(market.marketToken)).burn(
299 | * | address(params.withdrawalVault),
300 | * | withdrawal.marketTokenAmount()
301 | | );
302 | |
303 | * | params.withdrawalVault.syncTokenBalance(market.marketToken);
304 | |
305 | * | ExecuteWithdrawalResult memory result;
306 | * | (result.outputToken, result.outputAmount) = _swap(
307 | * | params,
308 | * | market,
309 | * | market.longToken,
310 | * | cache.longTokenOutputAmount,
311 | * | withdrawal.longTokenSwapPath(),
312 | * | withdrawal.minLongTokenAmount(),
313 | * | withdrawal.receiver(),
314 | * | withdrawal.uiFeeReceiver(),
315 | * | withdrawal.shouldUnwrapNativeToken()
316 | | );
317 | |
318 | * | (result.secondaryOutputToken, result.secondaryOutputAmount) = _swap(
319 | * | params,
320 | * | market,
321 | * | market.shortToken,
322 | * | cache.shortTokenOutputAmount,
323 | * | withdrawal.shortTokenSwapPath(),
324 | * | withdrawal.minShortTokenAmount(),
325 | * | withdrawal.receiver(),
326 | * | withdrawal.uiFeeReceiver(),
327 | * | withdrawal.shouldUnwrapNativeToken()
328 | | );
329 | |
330 | * | SwapPricingUtils.emitSwapFeesCollected(
331 | * | params.eventEmitter,
332 | * | params.key,
333 | * | market.marketToken,
334 | * | market.longToken,
335 | * | prices.longTokenPrice.min,
336 | | Keys.WITHDRAWAL_FEE_TYPE,
337 | * | cache.longTokenFees
338 | | );
339 | |
340 | * | SwapPricingUtils.emitSwapFeesCollected(
341 | * | params.eventEmitter,
342 | * | params.key,
343 | * | market.marketToken,
344 | * | market.shortToken,
345 | * | prices.shortTokenPrice.min,
346 | | Keys.WITHDRAWAL_FEE_TYPE,
347 | * | cache.shortTokenFees
348 | | );
349 | |
350 | | // if the native token was transferred to the receiver in a swap
351 | | // it may be possible to invoke internal contracts before the validations
352 | | // are called
353 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, market);
354 | |
355 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
356 | * | params.dataStore,
357 | * | market,
358 | * | prices.indexTokenPrice,
359 | * | prices.longTokenPrice,
360 | * | prices.shortTokenPrice,
361 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
362 | * | false
363 | | );
364 | |
365 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
366 | |
367 | * | MarketEventUtils.emitMarketPoolValueUpdated(
368 | * | params.eventEmitter,
369 | * | keccak256(abi.encode("WITHDRAWAL")),
370 | * | params.key,
371 | * | market.marketToken,
372 | * | poolValueInfo,
373 | * | marketTokensSupply
374 | | );
375 | |
376 | * | return result;
377 | | }
378 | |
379 | * | function _swap(
380 | | ExecuteWithdrawalParams memory params,
381 | | Market.Props memory market,
382 | | address tokenIn,
383 | | uint256 amountIn,
384 | | address[] memory swapPath,
385 | | uint256 minOutputAmount,
386 | | address receiver,
387 | | address uiFeeReceiver,
388 | | bool shouldUnwrapNativeToken
389 | * | ) internal returns (address, uint256) {
390 | * | SwapCache memory cache;
391 | |
392 | * | cache.swapPathMarkets = MarketUtils.getSwapPathMarkets(params.dataStore, swapPath);
393 | |
394 | * | cache.swapParams.dataStore = params.dataStore;
395 | * | cache.swapParams.eventEmitter = params.eventEmitter;
396 | * | cache.swapParams.oracle = params.oracle;
397 | * | cache.swapParams.bank = Bank(payable(market.marketToken));
398 | * | cache.swapParams.key = params.key;
399 | * | cache.swapParams.tokenIn = tokenIn;
400 | * | cache.swapParams.amountIn = amountIn;
401 | * | cache.swapParams.swapPathMarkets = cache.swapPathMarkets;
402 | * | cache.swapParams.minOutputAmount = minOutputAmount;
403 | * | cache.swapParams.receiver = receiver;
404 | * | cache.swapParams.uiFeeReceiver = uiFeeReceiver;
405 | * | cache.swapParams.shouldUnwrapNativeToken = shouldUnwrapNativeToken;
406 | |
407 | * | (cache.outputToken, cache.outputAmount) = SwapUtils.swap(cache.swapParams);
408 | |
409 | | // validate that internal state changes are correct before calling
410 | | // internal callbacks
411 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, cache.swapPathMarkets);
412 | |
413 | * | return (cache.outputToken, cache.outputAmount);
414 | | }
415 | |
416 | * | function _getOutputAmounts(
417 | | ExecuteWithdrawalParams memory params,
418 | | Market.Props memory market,
419 | | MarketUtils.MarketPrices memory prices,
420 | | uint256 marketTokenAmount
421 | * | ) internal returns (uint256, uint256) {
422 | | // the max pnl factor for withdrawals should be the lower of the max pnl factor values
423 | | // which means that pnl would be capped to a smaller amount and the pool
424 | | // value would be higher even if there is a large pnl
425 | | // this should be okay since MarketUtils.validateMaxPnl is called after the withdrawal
426 | | // which ensures that the max pnl factor for withdrawals was not exceeded
427 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
428 | * | params.dataStore,
429 | * | market,
430 | * | params.oracle.getPrimaryPrice(market.indexToken),
431 | * | prices.longTokenPrice,
432 | * | prices.shortTokenPrice,
433 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
434 | * | false
435 | | );
436 | |
437 | * | if (poolValueInfo.poolValue <= 0) {
438 | | revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);
439 | | }
440 | |
441 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256();
442 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
443 | |
444 | * | MarketEventUtils.emitMarketPoolValueInfo(
445 | * | params.eventEmitter,
446 | * | params.key,
447 | * | market.marketToken,
448 | * | poolValueInfo,
449 | * | marketTokensSupply
450 | | );
451 | |
452 | * | uint256 longTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.longToken);
453 | * | uint256 shortTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.shortToken);
454 | |
455 | * | uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;
456 | * | uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;
457 | |
458 | * | uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;
459 | |
460 | * | uint256 marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, poolValue, marketTokensSupply);
461 | |
462 | * | uint256 longTokenOutputUsd = Precision.mulDiv(marketTokensUsd, longTokenPoolUsd, totalPoolUsd);
463 | * | uint256 shortTokenOutputUsd = Precision.mulDiv(marketTokensUsd, shortTokenPoolUsd, totalPoolUsd);
464 | |
465 | * | return (
466 | * | longTokenOutputUsd / prices.longTokenPrice.max,
467 | * | shortTokenOutputUsd / prices.shortTokenPrice.max
468 | | );
469 | | }
470 | | }
471 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/Withdrawal.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | /**
6 | | * @title Withdrawal
7 | | * @dev Struct for withdrawals
8 | | */
9 | * | library Withdrawal {
10 | | // @dev there is a limit on the number of fields a struct can have when being passed
11 | | // or returned as a memory variable which can cause "Stack too deep" errors
12 | | // use sub-structs to avoid this issue
13 | | // @param addresses address values
14 | | // @param numbers number values
15 | | // @param flags boolean values
16 | | struct Props {
17 | | Addresses addresses;
18 | | Numbers numbers;
19 | | Flags flags;
20 | | }
21 | |
22 | | // @param account The account to withdraw for.
23 | | // @param receiver The address that will receive the withdrawn tokens.
24 | | // @param callbackContract The contract that will be called back.
25 | | // @param uiFeeReceiver The ui fee receiver.
26 | | // @param market The market on which the withdrawal will be executed.
27 | | struct Addresses {
28 | | address account;
29 | | address receiver;
30 | | address callbackContract;
31 | | address uiFeeReceiver;
32 | | address market;
33 | | address[] longTokenSwapPath;
34 | | address[] shortTokenSwapPath;
35 | | }
36 | |
37 | | // @param marketTokenAmount The amount of market tokens that will be withdrawn.
38 | | // @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.
39 | | // @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.
40 | | // @param updatedAtBlock The block at which the withdrawal was last updated.
41 | | // @param executionFee The execution fee for the withdrawal.
42 | | // @param callbackGasLimit The gas limit for calling the callback contract.
43 | | struct Numbers {
44 | | uint256 marketTokenAmount;
45 | | uint256 minLongTokenAmount;
46 | | uint256 minShortTokenAmount;
47 | | uint256 updatedAtBlock;
48 | | uint256 updatedAtTime;
49 | | uint256 executionFee;
50 | | uint256 callbackGasLimit;
51 | | }
52 | |
53 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when
54 | | struct Flags {
55 | | bool shouldUnwrapNativeToken;
56 | | }
57 | |
58 | * | function account(Props memory props) internal pure returns (address) {
59 | * | return props.addresses.account;
60 | | }
61 | |
62 | * | function setAccount(Props memory props, address value) internal pure {
63 | * | props.addresses.account = value;
64 | | }
65 | |
66 | * | function receiver(Props memory props) internal pure returns (address) {
67 | * | return props.addresses.receiver;
68 | | }
69 | |
70 | * | function setReceiver(Props memory props, address value) internal pure {
71 | * | props.addresses.receiver = value;
72 | | }
73 | |
74 | * | function callbackContract(Props memory props) internal pure returns (address) {
75 | * | return props.addresses.callbackContract;
76 | | }
77 | |
78 | * | function setCallbackContract(Props memory props, address value) internal pure {
79 | * | props.addresses.callbackContract = value;
80 | | }
81 | |
82 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) {
83 | * | return props.addresses.uiFeeReceiver;
84 | | }
85 | |
86 | * | function setUiFeeReceiver(Props memory props, address value) internal pure {
87 | * | props.addresses.uiFeeReceiver = value;
88 | | }
89 | |
90 | * | function market(Props memory props) internal pure returns (address) {
91 | * | return props.addresses.market;
92 | | }
93 | |
94 | * | function setMarket(Props memory props, address value) internal pure {
95 | * | props.addresses.market = value;
96 | | }
97 | |
98 | * | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
99 | * | return props.addresses.longTokenSwapPath;
100 | | }
101 | |
102 | * | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {
103 | * | props.addresses.longTokenSwapPath = value;
104 | | }
105 | |
106 | * | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
107 | * | return props.addresses.shortTokenSwapPath;
108 | | }
109 | |
110 | * | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {
111 | * | props.addresses.shortTokenSwapPath = value;
112 | | }
113 | |
114 | * | function marketTokenAmount(Props memory props) internal pure returns (uint256) {
115 | * | return props.numbers.marketTokenAmount;
116 | | }
117 | |
118 | * | function setMarketTokenAmount(Props memory props, uint256 value) internal pure {
119 | * | props.numbers.marketTokenAmount = value;
120 | | }
121 | |
122 | * | function minLongTokenAmount(Props memory props) internal pure returns (uint256) {
123 | * | return props.numbers.minLongTokenAmount;
124 | | }
125 | |
126 | * | function setMinLongTokenAmount(Props memory props, uint256 value) internal pure {
127 | * | props.numbers.minLongTokenAmount = value;
128 | | }
129 | |
130 | * | function minShortTokenAmount(Props memory props) internal pure returns (uint256) {
131 | * | return props.numbers.minShortTokenAmount;
132 | | }
133 | |
134 | * | function setMinShortTokenAmount(Props memory props, uint256 value) internal pure {
135 | * | props.numbers.minShortTokenAmount = value;
136 | | }
137 | |
138 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) {
139 | * | return props.numbers.updatedAtBlock;
140 | | }
141 | |
142 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
143 | * | props.numbers.updatedAtBlock = value;
144 | | }
145 | |
146 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) {
147 | * | return props.numbers.updatedAtTime;
148 | | }
149 | |
150 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
151 | * | props.numbers.updatedAtTime = value;
152 | | }
153 | |
154 | * | function executionFee(Props memory props) internal pure returns (uint256) {
155 | * | return props.numbers.executionFee;
156 | | }
157 | |
158 | * | function setExecutionFee(Props memory props, uint256 value) internal pure {
159 | * | props.numbers.executionFee = value;
160 | | }
161 | |
162 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) {
163 | * | return props.numbers.callbackGasLimit;
164 | | }
165 | |
166 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
167 | * | props.numbers.callbackGasLimit = value;
168 | | }
169 | |
170 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {
171 | * | return props.flags.shouldUnwrapNativeToken;
172 | | }
173 | |
174 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {
175 | * | props.flags.shouldUnwrapNativeToken = value;
176 | | }
177 | | }
178 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalEventUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../event/EventEmitter.sol";
6 | | import "../event/EventUtils.sol";
7 | | import "../utils/Cast.sol";
8 | |
9 | | import "./Withdrawal.sol";
10 | | import "./WithdrawalUtils.sol";
11 | | import "../pricing/ISwapPricingUtils.sol";
12 | |
13 | * | library WithdrawalEventUtils {
14 | | using Withdrawal for Withdrawal.Props;
15 | |
16 | | using EventUtils for EventUtils.AddressItems;
17 | | using EventUtils for EventUtils.UintItems;
18 | | using EventUtils for EventUtils.IntItems;
19 | | using EventUtils for EventUtils.BoolItems;
20 | | using EventUtils for EventUtils.Bytes32Items;
21 | | using EventUtils for EventUtils.BytesItems;
22 | | using EventUtils for EventUtils.StringItems;
23 | |
24 | * | function emitWithdrawalCreated(
25 | | EventEmitter eventEmitter,
26 | | bytes32 key,
27 | | Withdrawal.Props memory withdrawal,
28 | | WithdrawalUtils.WithdrawalType withdrawalType
29 | * | ) internal {
30 | * | EventUtils.EventLogData memory eventData;
31 | |
32 | * | eventData.addressItems.initItems(4);
33 | * | eventData.addressItems.setItem(0, "account", withdrawal.account());
34 | * | eventData.addressItems.setItem(1, "receiver", withdrawal.receiver());
35 | * | eventData.addressItems.setItem(2, "callbackContract", withdrawal.callbackContract());
36 | * | eventData.addressItems.setItem(3, "market", withdrawal.market());
37 | |
38 | * | eventData.addressItems.initArrayItems(2);
39 | * | eventData.addressItems.setItem(0, "longTokenSwapPath", withdrawal.longTokenSwapPath());
40 | * | eventData.addressItems.setItem(1, "shortTokenSwapPath", withdrawal.shortTokenSwapPath());
41 | |
42 | * | eventData.uintItems.initItems(8);
43 | * | eventData.uintItems.setItem(0, "marketTokenAmount", withdrawal.marketTokenAmount());
44 | * | eventData.uintItems.setItem(1, "minLongTokenAmount", withdrawal.minLongTokenAmount());
45 | * | eventData.uintItems.setItem(2, "minShortTokenAmount", withdrawal.minShortTokenAmount());
46 | * | eventData.uintItems.setItem(3, "updatedAtBlock", withdrawal.updatedAtBlock());
47 | * | eventData.uintItems.setItem(4, "updatedAtTime", withdrawal.updatedAtTime());
48 | * | eventData.uintItems.setItem(5, "executionFee", withdrawal.executionFee());
49 | * | eventData.uintItems.setItem(6, "callbackGasLimit", withdrawal.callbackGasLimit());
50 | * | eventData.uintItems.setItem(7, "withdrawalType", uint256(withdrawalType));
51 | |
52 | * | eventData.boolItems.initItems(1);
53 | * | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", withdrawal.shouldUnwrapNativeToken());
54 | |
55 | * | eventData.bytes32Items.initItems(1);
56 | * | eventData.bytes32Items.setItem(0, "key", key);
57 | |
58 | * | eventEmitter.emitEventLog2(
59 | | "WithdrawalCreated",
60 | * | key,
61 | * | Cast.toBytes32(withdrawal.account()),
62 | * | eventData
63 | | );
64 | | }
65 | |
66 | * | function emitWithdrawalExecuted(
67 | | EventEmitter eventEmitter,
68 | | bytes32 key,
69 | | address account,
70 | | ISwapPricingUtils.SwapPricingType swapPricingType
71 | * | ) internal {
72 | * | EventUtils.EventLogData memory eventData;
73 | |
74 | * | eventData.bytes32Items.initItems(1);
75 | * | eventData.bytes32Items.setItem(0, "key", key);
76 | |
77 | * | eventData.addressItems.initItems(1);
78 | * | eventData.addressItems.setItem(0, "account", account);
79 | |
80 | * | eventData.uintItems.initItems(1);
81 | * | eventData.uintItems.setItem(0, "swapPricingType", uint256(swapPricingType));
82 | |
83 | * | eventEmitter.emitEventLog2(
84 | | "WithdrawalExecuted",
85 | * | key,
86 | * | Cast.toBytes32(account),
87 | * | eventData
88 | | );
89 | | }
90 | |
91 | * | function emitWithdrawalCancelled(
92 | | EventEmitter eventEmitter,
93 | | bytes32 key,
94 | | address account,
95 | | string memory reason,
96 | | bytes memory reasonBytes
97 | * | ) internal {
98 | * | EventUtils.EventLogData memory eventData;
99 | |
100 | * | eventData.bytes32Items.initItems(1);
101 | * | eventData.bytes32Items.setItem(0, "key", key);
102 | |
103 | * | eventData.addressItems.initItems(1);
104 | * | eventData.addressItems.setItem(0, "account", account);
105 | |
106 | * | eventData.stringItems.initItems(1);
107 | * | eventData.stringItems.setItem(0, "reason", reason);
108 | |
109 | * | eventData.bytesItems.initItems(1);
110 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
111 | |
112 | * | eventEmitter.emitEventLog2(
113 | | "WithdrawalCancelled",
114 | * | key,
115 | * | Cast.toBytes32(account),
116 | * | eventData
117 | | );
118 | | }
119 | | }
120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalStoreUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../data/Keys.sol";
6 | | import "../data/DataStore.sol";
7 | |
8 | | import "./Withdrawal.sol";
9 | |
10 | | /**
11 | | * @title WithdrawalStoreUtils
12 | | * @dev Library for withdrawal storage functions
13 | | */
14 | * | library WithdrawalStoreUtils {
15 | | using Withdrawal for Withdrawal.Props;
16 | |
17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER"));
19 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
20 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
21 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET"));
22 | * | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH"));
23 | * | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH"));
24 | |
25 | * | bytes32 internal constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode("MARKET_TOKEN_AMOUNT"));
26 | * | bytes32 internal constant MIN_LONG_TOKEN_AMOUNT = keccak256(abi.encode("MIN_LONG_TOKEN_AMOUNT"));
27 | * | bytes32 internal constant MIN_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("MIN_SHORT_TOKEN_AMOUNT"));
28 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
29 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME"));
30 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
31 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
32 | |
33 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
34 | |
35 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Withdrawal.Props memory) {
36 | * | Withdrawal.Props memory withdrawal;
37 | * | if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {
38 | * | return withdrawal;
39 | | }
40 | |
41 | * | withdrawal.setAccount(dataStore.getAddress(
42 | * | keccak256(abi.encode(key, ACCOUNT))
43 | | ));
44 | |
45 | * | withdrawal.setReceiver(dataStore.getAddress(
46 | * | keccak256(abi.encode(key, RECEIVER))
47 | | ));
48 | |
49 | * | withdrawal.setCallbackContract(dataStore.getAddress(
50 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
51 | | ));
52 | |
53 | * | withdrawal.setUiFeeReceiver(dataStore.getAddress(
54 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
55 | | ));
56 | |
57 | * | withdrawal.setMarket(dataStore.getAddress(
58 | * | keccak256(abi.encode(key, MARKET))
59 | | ));
60 | |
61 | * | withdrawal.setLongTokenSwapPath(dataStore.getAddressArray(
62 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
63 | | ));
64 | |
65 | * | withdrawal.setShortTokenSwapPath(dataStore.getAddressArray(
66 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
67 | | ));
68 | |
69 | * | withdrawal.setMarketTokenAmount(dataStore.getUint(
70 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
71 | | ));
72 | |
73 | * | withdrawal.setMinLongTokenAmount(dataStore.getUint(
74 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))
75 | | ));
76 | |
77 | * | withdrawal.setMinShortTokenAmount(dataStore.getUint(
78 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))
79 | | ));
80 | |
81 | * | withdrawal.setUpdatedAtBlock(dataStore.getUint(
82 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
83 | | ));
84 | |
85 | * | withdrawal.setUpdatedAtTime(dataStore.getUint(
86 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
87 | | ));
88 | |
89 | * | withdrawal.setExecutionFee(dataStore.getUint(
90 | * | keccak256(abi.encode(key, EXECUTION_FEE))
91 | | ));
92 | |
93 | * | withdrawal.setCallbackGasLimit(dataStore.getUint(
94 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
95 | | ));
96 | |
97 | * | withdrawal.setShouldUnwrapNativeToken(dataStore.getBool(
98 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
99 | | ));
100 | |
101 | * | return withdrawal;
102 | | }
103 | |
104 | * | function set(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) internal {
105 | * | dataStore.addBytes32(
106 | | Keys.WITHDRAWAL_LIST,
107 | * | key
108 | | );
109 | |
110 | * | dataStore.addBytes32(
111 | * | Keys.accountWithdrawalListKey(withdrawal.account()),
112 | * | key
113 | | );
114 | |
115 | * | dataStore.setAddress(
116 | * | keccak256(abi.encode(key, ACCOUNT)),
117 | * | withdrawal.account()
118 | | );
119 | |
120 | * | dataStore.setAddress(
121 | * | keccak256(abi.encode(key, RECEIVER)),
122 | * | withdrawal.receiver()
123 | | );
124 | |
125 | * | dataStore.setAddress(
126 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)),
127 | * | withdrawal.callbackContract()
128 | | );
129 | |
130 | * | dataStore.setAddress(
131 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)),
132 | * | withdrawal.uiFeeReceiver()
133 | | );
134 | |
135 | * | dataStore.setAddress(
136 | * | keccak256(abi.encode(key, MARKET)),
137 | * | withdrawal.market()
138 | | );
139 | |
140 | * | dataStore.setAddressArray(
141 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),
142 | * | withdrawal.longTokenSwapPath()
143 | | );
144 | |
145 | * | dataStore.setAddressArray(
146 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),
147 | * | withdrawal.shortTokenSwapPath()
148 | | );
149 | |
150 | * | dataStore.setUint(
151 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),
152 | * | withdrawal.marketTokenAmount()
153 | | );
154 | |
155 | * | dataStore.setUint(
156 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)),
157 | * | withdrawal.minLongTokenAmount()
158 | | );
159 | |
160 | * | dataStore.setUint(
161 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)),
162 | * | withdrawal.minShortTokenAmount()
163 | | );
164 | |
165 | * | dataStore.setUint(
166 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
167 | * | withdrawal.updatedAtBlock()
168 | | );
169 | |
170 | * | dataStore.setUint(
171 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)),
172 | * | withdrawal.updatedAtTime()
173 | | );
174 | |
175 | * | dataStore.setUint(
176 | * | keccak256(abi.encode(key, EXECUTION_FEE)),
177 | * | withdrawal.executionFee()
178 | | );
179 | |
180 | * | dataStore.setUint(
181 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
182 | * | withdrawal.callbackGasLimit()
183 | | );
184 | |
185 | * | dataStore.setBool(
186 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
187 | * | withdrawal.shouldUnwrapNativeToken()
188 | | );
189 | | }
190 | |
191 | * | function remove(DataStore dataStore, bytes32 key, address account) internal {
192 | * | if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {
193 | * | revert Errors.WithdrawalNotFound(key);
194 | | }
195 | |
196 | * | dataStore.removeBytes32(
197 | | Keys.WITHDRAWAL_LIST,
198 | * | key
199 | | );
200 | |
201 | * | dataStore.removeBytes32(
202 | * | Keys.accountWithdrawalListKey(account),
203 | * | key
204 | | );
205 | |
206 | * | dataStore.removeAddress(
207 | * | keccak256(abi.encode(key, ACCOUNT))
208 | | );
209 | |
210 | * | dataStore.removeAddress(
211 | * | keccak256(abi.encode(key, RECEIVER))
212 | | );
213 | |
214 | * | dataStore.removeAddress(
215 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT))
216 | | );
217 | |
218 | * | dataStore.removeAddress(
219 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER))
220 | | );
221 | |
222 | * | dataStore.removeAddress(
223 | * | keccak256(abi.encode(key, MARKET))
224 | | );
225 | |
226 | * | dataStore.removeAddressArray(
227 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
228 | | );
229 | |
230 | * | dataStore.removeAddressArray(
231 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
232 | | );
233 | |
234 | * | dataStore.removeUint(
235 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
236 | | );
237 | |
238 | * | dataStore.removeUint(
239 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))
240 | | );
241 | |
242 | * | dataStore.removeUint(
243 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))
244 | | );
245 | |
246 | * | dataStore.removeUint(
247 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK))
248 | | );
249 | |
250 | * | dataStore.removeUint(
251 | * | keccak256(abi.encode(key, UPDATED_AT_TIME))
252 | | );
253 | |
254 | * | dataStore.removeUint(
255 | * | keccak256(abi.encode(key, EXECUTION_FEE))
256 | | );
257 | |
258 | * | dataStore.removeUint(
259 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
260 | | );
261 | |
262 | * | dataStore.removeBool(
263 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
264 | | );
265 | | }
266 | |
267 | | function getWithdrawalCount(DataStore dataStore) internal view returns (uint256) {
268 | | return dataStore.getBytes32Count(Keys.WITHDRAWAL_LIST);
269 | | }
270 | |
271 | | function getWithdrawalKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
272 | | return dataStore.getBytes32ValuesAt(Keys.WITHDRAWAL_LIST, start, end);
273 | | }
274 | |
275 | | function getAccountWithdrawalCount(DataStore dataStore, address account) internal view returns (uint256) {
276 | | return dataStore.getBytes32Count(Keys.accountWithdrawalListKey(account));
277 | | }
278 | |
279 | | function getAccountWithdrawalKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
280 | | return dataStore.getBytes32ValuesAt(Keys.accountWithdrawalListKey(account), start, end);
281 | | }
282 | | }
283 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalUtils.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../adl/AdlUtils.sol";
6 | |
7 | | import "../data/DataStore.sol";
8 | |
9 | | import "./WithdrawalVault.sol";
10 | | import "./WithdrawalStoreUtils.sol";
11 | | import "./WithdrawalEventUtils.sol";
12 | |
13 | | import "../nonce/NonceUtils.sol";
14 | | import "../pricing/SwapPricingUtils.sol";
15 | | import "../oracle/Oracle.sol";
16 | | import "../oracle/OracleUtils.sol";
17 | |
18 | | import "../gas/GasUtils.sol";
19 | | import "../callback/CallbackUtils.sol";
20 | |
21 | | import "../utils/Array.sol";
22 | | import "../utils/AccountUtils.sol";
23 | |
24 | | /**
25 | | * @title WithdrawalUtils
26 | | * @dev Library for withdrawal functions
27 | | */
28 | * | library WithdrawalUtils {
29 | | using SafeCast for uint256;
30 | | using SafeCast for int256;
31 | | using Array for uint256[];
32 | | using Price for Price.Props;
33 | | using Withdrawal for Withdrawal.Props;
34 | |
35 | | using EventUtils for EventUtils.AddressItems;
36 | | using EventUtils for EventUtils.UintItems;
37 | | using EventUtils for EventUtils.IntItems;
38 | | using EventUtils for EventUtils.BoolItems;
39 | | using EventUtils for EventUtils.Bytes32Items;
40 | | using EventUtils for EventUtils.BytesItems;
41 | | using EventUtils for EventUtils.StringItems;
42 | |
43 | | enum WithdrawalType {
44 | | Normal,
45 | | Shift,
46 | | Glv
47 | | }
48 | |
49 | | /**
50 | | * @param receiver The address that will receive the withdrawal tokens.
51 | | * @param callbackContract The contract that will be called back.
52 | | * @param market The market on which the withdrawal will be executed.
53 | | * @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn.
54 | | * @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn.
55 | | * @param shouldUnwrapNativeToken Whether the native token should be unwrapped when executing the withdrawal.
56 | | * @param executionFee The execution fee for the withdrawal.
57 | | * @param callbackGasLimit The gas limit for calling the callback contract.
58 | | */
59 | | struct CreateWithdrawalParams {
60 | | address receiver;
61 | | address callbackContract;
62 | | address uiFeeReceiver;
63 | | address market;
64 | | address[] longTokenSwapPath;
65 | | address[] shortTokenSwapPath;
66 | | uint256 minLongTokenAmount;
67 | | uint256 minShortTokenAmount;
68 | | bool shouldUnwrapNativeToken;
69 | | uint256 executionFee;
70 | | uint256 callbackGasLimit;
71 | | }
72 | |
73 | | /**
74 | | * @dev Creates a withdrawal in the withdrawal store.
75 | | *
76 | | * @param dataStore The data store where withdrawal data is stored.
77 | | * @param eventEmitter The event emitter that is used to emit events.
78 | | * @param withdrawalVault WithdrawalVault.
79 | | * @param account The account that initiated the withdrawal.
80 | | * @param params The parameters for creating the withdrawal.
81 | | * @return The unique identifier of the created withdrawal.
82 | | */
83 | * | function createWithdrawal(
84 | | DataStore dataStore,
85 | | EventEmitter eventEmitter,
86 | | WithdrawalVault withdrawalVault,
87 | | address account,
88 | | CreateWithdrawalParams memory params
89 | * | ) internal returns (bytes32) {
90 | * | AccountUtils.validateAccount(account);
91 | |
92 | * | address wnt = TokenUtils.wnt(dataStore);
93 | * | uint256 wntAmount = withdrawalVault.recordTransferIn(wnt);
94 | |
95 | * | if (wntAmount < params.executionFee) {
96 | | revert Errors.InsufficientWntAmount(wntAmount, params.executionFee);
97 | | }
98 | |
99 | * | AccountUtils.validateReceiver(params.receiver);
100 | |
101 | * | uint256 marketTokenAmount = withdrawalVault.recordTransferIn(params.market);
102 | |
103 | * | if (marketTokenAmount == 0) {
104 | * | revert Errors.EmptyWithdrawalAmount();
105 | | }
106 | |
107 | * | params.executionFee = wntAmount;
108 | |
109 | * | MarketUtils.validateEnabledMarket(dataStore, params.market);
110 | * | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath);
111 | * | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath);
112 | |
113 | * | Withdrawal.Props memory withdrawal = Withdrawal.Props(
114 | * | Withdrawal.Addresses(
115 | * | account,
116 | * | params.receiver,
117 | * | params.callbackContract,
118 | * | params.uiFeeReceiver,
119 | * | params.market,
120 | * | params.longTokenSwapPath,
121 | * | params.shortTokenSwapPath
122 | | ),
123 | * | Withdrawal.Numbers(
124 | * | marketTokenAmount,
125 | * | params.minLongTokenAmount,
126 | * | params.minShortTokenAmount,
127 | * | Chain.currentBlockNumber(),
128 | * | Chain.currentTimestamp(),
129 | * | params.executionFee,
130 | * | params.callbackGasLimit
131 | | ),
132 | * | Withdrawal.Flags(
133 | * | params.shouldUnwrapNativeToken
134 | | )
135 | | );
136 | |
137 | * | CallbackUtils.validateCallbackGasLimit(dataStore, withdrawal.callbackGasLimit());
138 | |
139 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);
140 | * | uint256 oraclePriceCount = GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length);
141 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount);
142 | |
143 | * | bytes32 key = NonceUtils.getNextKey(dataStore);
144 | |
145 | * | WithdrawalStoreUtils.set(dataStore, key, withdrawal);
146 | |
147 | * | WithdrawalEventUtils.emitWithdrawalCreated(eventEmitter, key, withdrawal, WithdrawalType.Normal);
148 | |
149 | * | return key;
150 | | }
151 | |
152 | | /**
153 | | * @dev Cancels a withdrawal.
154 | | * @param dataStore The data store.
155 | | * @param eventEmitter The event emitter.
156 | | * @param withdrawalVault The withdrawal vault.
157 | | * @param key The withdrawal key.
158 | | * @param keeper The keeper sending the transaction.
159 | | * @param startingGas The starting gas for the transaction.
160 | | */
161 | * | function cancelWithdrawal(
162 | | DataStore dataStore,
163 | | EventEmitter eventEmitter,
164 | | WithdrawalVault withdrawalVault,
165 | | bytes32 key,
166 | | address keeper,
167 | | uint256 startingGas,
168 | | string memory reason,
169 | | bytes memory reasonBytes
170 | * | ) internal {
171 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this
172 | * | startingGas -= gasleft() / 63;
173 | |
174 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
175 | |
176 | * | if (withdrawal.account() == address(0)) {
177 | * | revert Errors.EmptyWithdrawal();
178 | | }
179 | |
180 | * | if (withdrawal.marketTokenAmount() == 0) {
181 | | revert Errors.EmptyWithdrawalAmount();
182 | | }
183 | |
184 | * | WithdrawalStoreUtils.remove(dataStore, key, withdrawal.account());
185 | |
186 | * | withdrawalVault.transferOut(
187 | * | withdrawal.market(),
188 | * | withdrawal.account(),
189 | * | withdrawal.marketTokenAmount(),
190 | * | false // shouldUnwrapNativeToken
191 | | );
192 | |
193 | * | WithdrawalEventUtils.emitWithdrawalCancelled(
194 | * | eventEmitter,
195 | * | key,
196 | * | withdrawal.account(),
197 | * | reason,
198 | * | reasonBytes
199 | | );
200 | |
201 | * | EventUtils.EventLogData memory eventData;
202 | * | CallbackUtils.afterWithdrawalCancellation(key, withdrawal, eventData);
203 | |
204 | * | GasUtils.payExecutionFee(
205 | * | dataStore,
206 | * | eventEmitter,
207 | * | withdrawalVault,
208 | * | key,
209 | * | withdrawal.callbackContract(),
210 | * | withdrawal.executionFee(),
211 | * | startingGas,
212 | * | GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length),
213 | * | keeper,
214 | * | withdrawal.receiver()
215 | | );
216 | | }
217 | | }
218 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalVault.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../bank/StrictBank.sol";
6 | |
7 | | // @title WithdrawalVault
8 | | // @dev Vault for withdrawals
9 | * | contract WithdrawalVault is StrictBank {
10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
11 | | }
12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/FuzzEchidna.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./helpers/GMXSetup.sol";
6 | |
7 | *r | contract FuzzEchidna is GMXSetup {
8 | | constructor() payable {
9 | | SetUpGMX();
10 | | }
11 | |
12 | | receive() external payable {}
13 | | }
14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/config/FuzzConfig.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../setup/FuzzSetup.sol";
6 | |
7 | | contract FuzzConfig is FuzzSetup {
8 | | //GMX CONFIG
9 | * | uint256 constant DECREASE_POSITION_DELTA_MIN = 1e30;
10 | * | uint256 constant RANDOMIZER_DIVISOR = 4545242;
11 | * | uint256 constant DECREASE_POSITION_TOLERABLE_PRICE_SUB = 1e10; //FROM 1e30
12 | |
13 | * | uint256 constant WETH_MIN_PRICE = 1000e4;
14 | * | uint256 constant WBTC_MIN_PRICE = 1000e2;
15 | * | uint256 constant USDT_MIN_PRICE = 1e6;
16 | * | uint256 constant USDC_MIN_PRICE = 1e6;
17 | * | uint256 constant SOL_MIN_PRICE = 1e4;
18 | |
19 | * | uint256 constant WETH_MAX_PRICE = 1_000_000e4;
20 | * | uint256 constant WBTC_MAX_PRICE = 1_000_000e2;
21 | * | uint256 constant USDT_MAX_PRICE = 1e6;
22 | * | uint256 constant USDC_MAX_PRICE = 1e6;
23 | * | uint256 constant SOL_MAX_PRICE = 1_000_000e4;
24 | |
25 | | //uint256 constant WETH_MAX_AMOUNT is a balance of native ETH or user
26 | * | uint256 constant WBTC_MAX_AMOUNT = 15_000e8;
27 | * | uint256 constant USDT_MAX_AMOUNT = 1000_000_000e6;
28 | * | uint256 constant USDC_MAX_AMOUNT = 1000_000_000e6;
29 | * | uint256 constant SOL_MAX_AMOUNT = 1000000e9;
30 | |
31 | * | uint256 constant WETH_MIN_AMOUNT = 1e16;
32 | * | uint256 constant WBTC_MIN_AMOUNT = 1e6;
33 | * | uint256 constant USDT_MIN_AMOUNT = 1e6;
34 | * | uint256 constant USDC_MIN_AMOUNT = 1e6;
35 | * | uint256 constant SOL_MIN_AMOUNT = 1e8;
36 | |
37 | * | uint256 constant FIXED_EXECUTION_FEE_AMOUNT = 1e10;
38 | * | bool constant SWAPS_ENABLED = false;
39 | | uint constant MIN_AMOUNT_TO_SHIFT = 1e16;
40 | | }
41 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/ADLSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./PropertiesSetup.sol";
6 | |
7 | | contract ADLSetup is PropertiesSetup {
8 | | struct ADL_cache {
9 | | bytes callData_SwitchADL;
10 | | bool success_SwitchADL;
11 | | bytes returnData_SwitchADL;
12 | | bytes callData_ExecuteADL;
13 | | bool success_ExecuteADL;
14 | | bytes returnData_ExecuteADL;
15 | | bytes callData_SwitchADL_back;
16 | | bool success_SwitchADL_back;
17 | | bytes returnData_SwitchADL_back;
18 | | }
19 | * | function ExecuteADLonVault(uint8 userIndex, uint seed) public {
20 | * | (, , , address user) = _gamma_getVault(userIndex); //gmxUtils is a holder of position
21 | |
22 | * | Position.Props[] memory positions = reader.getAccountPositions(
23 | * | dataStore,
24 | * | user,
25 | * | 0,
26 | * | 10
27 | | );
28 | * | Position.Props memory positionToADL = positions[0];
29 | |
30 | * | bytes32 positionKey = Position.getPositionKey(
31 | * | user,
32 | * | positionToADL.addresses.market,
33 | * | positionToADL.addresses.collateralToken,
34 | * | positionToADL.flags.isLong
35 | | );
36 | |
37 | * | Market.Props memory marketProps = MarketStoreUtils.get(
38 | * | dataStore,
39 | * | positionToADL.addresses.market
40 | | );
41 | |
42 | * | TokenPrices memory tokenPrices = _setTokenPrices(
43 | * | seed //priceseed for the max price
44 | | );
45 | |
46 | * | ReaderUtils.PositionInfo memory positionInfo = reader.getPositionInfo(
47 | * | dataStore,
48 | * | referralStorage,
49 | * | positionKey,
50 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
51 | * | 0, //size delta usd == 0 because usePositionSizeAsSizeDeltaUsd is true
52 | * | address(0), //uiFeeReceiver
53 | * | true //usePositionSizeAsSizeDeltaUsd
54 | | );
55 | |
56 | * | uint reduceSizeBy = clampBetween(
57 | * | seed,
58 | * | 1,
59 | * | positionInfo.position.numbers.sizeInUsd
60 | | );
61 | |
62 | * | _adl(
63 | * | marketProps,
64 | * | user,
65 | * | positionToADL.addresses.market,
66 | * | positionToADL.flags.isLong,
67 | * | positionToADL.addresses.collateralToken,
68 | * | reduceSizeBy,
69 | * | tokenPrices
70 | | );
71 | |
72 | * | ReaderUtils.PositionInfo memory positionInfoAfter = reader
73 | | .getPositionInfo(
74 | * | dataStore,
75 | * | referralStorage,
76 | * | positionKey,
77 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
78 | * | 0, //size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true
79 | * | address(0),
80 | * | true //usePositionSizeAsSizeDeltaUsd
81 | | );
82 | |
83 | * | invariantPositionSizeUSDShouldDecrease(
84 | * | positionInfo.position.numbers.sizeInUsd,
85 | * | positionInfoAfter.position.numbers.sizeInUsd,
86 | * | reduceSizeBy
87 | | );
88 | | }
89 | |
90 | * | function ExecuteADL(uint8 userIndex, uint seed) public {
91 | * | address user = _getRandomUser(userIndex);
92 | |
93 | * | Position.Props[] memory positions = reader.getAccountPositions(
94 | * | dataStore,
95 | * | user,
96 | * | 0,
97 | * | 10
98 | | );
99 | * | Position.Props memory positionToADL = positions[0];
100 | |
101 | * | bytes32 positionKey = Position.getPositionKey(
102 | * | user,
103 | * | positionToADL.addresses.market,
104 | * | positionToADL.addresses.collateralToken,
105 | * | positionToADL.flags.isLong
106 | | );
107 | |
108 | * | Market.Props memory marketProps = MarketStoreUtils.get(
109 | * | dataStore,
110 | * | positionToADL.addresses.market
111 | | );
112 | |
113 | * | TokenPrices memory tokenPrices = _setTokenPrices(
114 | * | seed //priceseed for the max price
115 | | );
116 | |
117 | * | ReaderUtils.PositionInfo memory positionInfo = reader.getPositionInfo(
118 | * | dataStore,
119 | * | referralStorage,
120 | * | positionKey,
121 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
122 | * | 0, //size delta usd == 0 because usePositionSizeAsSizeDeltaUsd is true
123 | * | address(0), //uiFeeReceiver
124 | * | true //usePositionSizeAsSizeDeltaUsd
125 | | );
126 | |
127 | * | uint reduceSizeBy = clampBetween(
128 | * | seed,
129 | * | 1,
130 | * | positionInfo.position.numbers.sizeInUsd
131 | | );
132 | |
133 | * | _adl(
134 | * | marketProps,
135 | * | user,
136 | * | positionToADL.addresses.market,
137 | * | positionToADL.flags.isLong,
138 | * | positionToADL.addresses.collateralToken,
139 | * | reduceSizeBy,
140 | * | tokenPrices
141 | | );
142 | |
143 | * | ReaderUtils.PositionInfo memory positionInfoAfter = reader
144 | | .getPositionInfo(
145 | * | dataStore,
146 | * | referralStorage,
147 | * | positionKey,
148 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
149 | * | 0, //size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true
150 | * | address(0),
151 | * | true //usePositionSizeAsSizeDeltaUsd
152 | | );
153 | |
154 | * | invariantPositionSizeUSDShouldDecrease(
155 | * | positionInfo.position.numbers.sizeInUsd,
156 | * | positionInfoAfter.position.numbers.sizeInUsd,
157 | * | reduceSizeBy
158 | | );
159 | | }
160 | |
161 | * | function _adl(
162 | | Market.Props memory marketProps,
163 | | address user,
164 | | address market,
165 | | bool isLong,
166 | | address collateralToken,
167 | | uint reduceSizeBy,
168 | | TokenPrices memory tokenPrices
169 | * | ) internal {
170 | * | ADL_cache memory cache;
171 | |
172 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
173 | * | tokenPrices.tokens,
174 | * | tokenPrices.maxPrices,
175 | * | tokenPrices.minPrices
176 | | );
177 | |
178 | * | cache.callData_SwitchADL = abi.encodeWithSelector(
179 | * | adlHandler.updateAdlState.selector,
180 | * | market,
181 | * | isLong,
182 | * | oracleParams
183 | | );
184 | |
185 | * | vm.prank(DEPLOYER);
186 | * | adlHandler.updateAdlState(market, isLong, oracleParams);
187 | |
188 | * | vm.prank(DEPLOYER);
189 | *r | adlHandler.executeAdl(
190 | * | user,
191 | * | market,
192 | * | collateralToken,
193 | * | isLong,
194 | * | reduceSizeBy,
195 | * | oracleParams
196 | | );
197 | |
198 | | //Switching prices back to minimum and disabling ADL
199 | * | TokenPrices memory lowestTokenPrices = _setTokenPrices(1000e4);
200 | |
201 | * | OracleUtils.SetPricesParams
202 | * | memory oracleParamsSwitchADL = SetOraclePrices(
203 | * | lowestTokenPrices.tokens,
204 | * | lowestTokenPrices.maxPrices,
205 | * | lowestTokenPrices.minPrices
206 | | );
207 | |
208 | * | vm.prank(DEPLOYER);
209 | * | adlHandler.updateAdlState(market, isLong, oracleParams);
210 | * | bool isAdlEnabled = dataStore.getBool(
211 | * | Keys.isAdlEnabledKey(market, isLong)
212 | | );
213 | |
214 | * | require(!isAdlEnabled, "ADL should be disabled");
215 | | }
216 | | }
217 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/BaseSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "../config/FuzzConfig.sol";
5 | | import "../interfaces/IMockDex.sol";
6 | |
7 | | contract BaseSetup is FuzzConfig {
8 | | mapping(address => uint256) internal tokenMinAmounts;
9 | | mapping(address => uint256) internal tokenMaxAmounts;
10 | | mapping(address => uint256) internal tokenMinPrice;
11 | | mapping(address => uint256) internal tokenMaxPrice;
12 | |
13 | | /**
14 | | .-",
15 | | `~ ||
16 | | ||___ GAMMA Structs
17 | | (':.)`
18 | | || ||
19 | | || ||
20 | | ^^ ^^
21 | | */
22 | | struct DepositInfo {
23 | | uint256 amount;
24 | | uint256 shares;
25 | | address owner;
26 | | uint256 timestamp;
27 | | address recipient;
28 | | }
29 | | enum PROTOCOL {
30 | | DEX,
31 | | GMX
32 | | }
33 | |
34 | | struct SwapProgress {
35 | | // swap process involves asynchronous operation so store swap progress data
36 | | bool isCollateralToIndex; // if swap `collateralToken` to `indexToken`, true and vice versa.
37 | | uint256 swapped; // the amount of output token that has already been swapped.
38 | | uint256 remaining; // the amount of input token that remains to be swapped
39 | | }
40 | |
41 | | enum NextActionSelector {
42 | | NO_ACTION, // state where no action is required
43 | | INCREASE_ACTION, // represents increasing actions such as increasing a GMX perps position or increasing a spot position
44 | | SWAP_ACTION, // represents swapping a token, either collateral to index or vice versa
45 | | WITHDRAW_ACTION, // represents withdrawing funds
46 | | COMPOUND_ACTION, // whenver claiming positive funding fee, we could have idle funds in the vault.
47 | | // If it's enough to deposit more into GMX, triggers `COMPOUND_ACTION`.
48 | | SETTLE_ACTION, // settle fees and ensure state is up-to-date prior to withdrawals
49 | | FINALIZE
50 | | }
51 | |
52 | | enum FLOW {
53 | | NONE,
54 | | DEPOSIT,
55 | | SIGNAL_CHANGE,
56 | | WITHDRAW,
57 | | COMPOUND
58 | | }
59 | |
60 | | struct UserState {
61 | | uint USDCBalance;
62 | | uint256 totalAmount;
63 | | uint256 totalShares;
64 | | uint256[] depositIds;
65 | | mapping(uint256 => uint) deposits; //depositID => deposit amount
66 | | uint256 lastDepositTimestamp;
67 | | uint256 shareValue;
68 | | }
69 | | struct Action {
70 | | NextActionSelector selector;
71 | | bytes data;
72 | | }
73 | | struct VaultInfo {
74 | | mapping(address => UserState) userStates;
75 | | uint256 totalAmount;
76 | | uint256 vaultUSDCBalance;
77 | | uint256 totalSharesCalculated;
78 | | uint256 oldestDepositTimestamp;
79 | | uint256 newestDepositTimestamp;
80 | | uint256 totalShares;
81 | | uint256 counter;
82 | | bytes32 curPositionKey;
83 | | uint256 totalDepositAmount;
84 | | bool beenLong;
85 | | bool positionIsClosed;
86 | | bool gmxLock;
87 | | bool isBusy;
88 | | bool isLocked;
89 | | NextActionSelector nextActionSelector;
90 | | uint treasuryBalance;
91 | | uint256 shareValue;
92 | | uint256 totalFees;
93 | | uint256 collateralAmount;
94 | | }
95 | | struct State {
96 | | mapping(address => VaultInfo) vaultInfos;
97 | | }
98 | |
99 | | mapping(uint8 => State) internal states;
100 | |
101 | | struct gammaWithdrawal {
102 | | address user;
103 | | address vault;
104 | | uint256 depositId;
105 | | }
106 | |
107 | | gammaWithdrawal internal withdrawalAssertionInputs;
108 | |
109 | | /**
110 | | .-",
111 | | `~ ||
112 | | ||___ DEPOSIT Structs
113 | | (':.)`
114 | | || ||
115 | | || ||
116 | | ^^ ^^
117 | | */
118 | |
119 | | struct DepositorParams {
120 | | address user;
121 | | uint256 longAmount;
122 | | uint256 shortAmount;
123 | | bool isWETH;
124 | | }
125 | |
126 | | struct DepositParams {
127 | | address receiver;
128 | | address callbackContract;
129 | | address uiFeeReceiver;
130 | | address[] longTokenSwapPath;
131 | | address[] shortTokenSwapPath;
132 | | uint256 minMarketTokens;
133 | | bool shouldUnwrapNativeToken;
134 | | uint256 executionFee;
135 | | uint256 callbackGasLimit;
136 | | }
137 | |
138 | | struct DepositCreated {
139 | | DepositState beforeDepositExec;
140 | | DepositParams depositParams;
141 | | DepositorParams depositorParams;
142 | | DepositUtils.CreateDepositParams createDepositParams;
143 | | address[] longSwapPath;
144 | | address[] shortSwapPath;
145 | | bytes32 key;
146 | | TokenPrices tokenPrices;
147 | | }
148 | |
149 | | struct DepositState {
150 | | address market;
151 | | address user;
152 | | uint marketTotalSupply;
153 | | uint userBalanceMarket;
154 | | uint userBalanceLong;
155 | | uint userBalanceShort;
156 | | uint vaultBalanceLong;
157 | | uint vaultBalanceShort;
158 | | uint simulateDepositAmountOut;
159 | | uint longAmountFromParams;
160 | | uint shortAmountFromParams;
161 | | }
162 | |
163 | | /**
164 | | .-",
165 | | `~ ||
166 | | ||___ SHIFT Structs
167 | | (':.)`
168 | | || ||
169 | | || ||
170 | | ^^ ^^
171 | | */
172 | |
173 | | struct ShiftCreated {
174 | | ShiftState beforeExec;
175 | | ShiftUtils.CreateShiftParams createShiftParams;
176 | | uint marketTokenAmount;
177 | | bytes32 key;
178 | | }
179 | |
180 | | struct ShiftMarketData {
181 | | int marketTokenPriceFrom;
182 | | int marketTokenPriceTo;
183 | | uint simulateLongTokenAmountWithdrawal;
184 | | uint simulateShortTokenAmountWithdrawal;
185 | | }
186 | |
187 | | struct ShiftState {
188 | | ShiftUtils.CreateShiftParams createShiftParams;
189 | | ShiftMarketData marketDataBefore;
190 | | ShiftMarketData marketDataAfter;
191 | | uint marketTokenAmount;
192 | | TokenPrices tokenPrices;
193 | | address user;
194 | | uint marketFromBalance;
195 | | uint marketToBalance;
196 | | uint longTokenPoolAmountMarketFrom;
197 | | uint shortTokenPoolAmountMarketFrom;
198 | | uint longTokenPoolAmountMarketTo;
199 | | uint shortTokenPoolAmountMarketTo;
200 | | uint longTokenMarketFeeAmountMarketFrom;
201 | | uint shortTokenMarketFeeAmountMarketFrom;
202 | | }
203 | |
204 | | /**
205 | | .-",
206 | | `~ ||
207 | | ||___ POSITION Structs
208 | | (':.)`
209 | | || ||
210 | | || ||
211 | | ^^ ^^
212 | | */
213 | |
214 | | struct OrderCreated {
215 | | IBaseOrderUtils.CreateOrderParams createOrderParams;
216 | | bytes32 key;
217 | | uint256 updatedAt;
218 | | address user;
219 | | bytes32 handlerType;
220 | | uint amountSent;
221 | | bool isClose;
222 | | uint8 swapPathSeed;
223 | | TokenPrices tokenPrices;
224 | | uint executionFee;
225 | | }
226 | |
227 | | struct PositionState {
228 | | uint sizeInUsd;
229 | | uint sizeInTokens;
230 | | uint collateralAmount;
231 | | bool isLong;
232 | | uint OILong;
233 | | uint OILongLatestMarket;
234 | | uint OIShort;
235 | | uint collateralSumLong;
236 | | uint collateralSumShort;
237 | | uint balanceOfLongToken;
238 | | uint balanceOfShortToken;
239 | | }
240 | |
241 | | struct SwapState {
242 | | uint balanceOfOutputToken;
243 | | uint balanceOfInputToken;
244 | | address outputToken;
245 | | SwapResult swapResult;
246 | | }
247 | |
248 | | struct SwapResult {
249 | | uint256 amountOut;
250 | | uint256 amountAfterFees;
251 | | int256 totalImpactAmount;
252 | | SwapPricingUtils.SwapFees totalFees;
253 | | }
254 | |
255 | | struct GetAmountsOutCache {
256 | | Market.Props market;
257 | | MarketUtils.MarketPrices prices;
258 | | address currentToken;
259 | | uint currentAmount;
260 | | address uiFeeReceiver;
261 | | }
262 | | /**
263 | | .-",
264 | | `~ ||
265 | | ||___ WITHDRAWAL Structs
266 | | (':.)`
267 | | || ||
268 | | || ||
269 | | ^^ ^^
270 | | */
271 | |
272 | | struct WithdrawalCreated {
273 | | WithdrawalUtils.CreateWithdrawalParams withdrawalParams;
274 | | uint amount;
275 | | bytes32 withdrawalKey;
276 | | }
277 | |
278 | | struct WithdrawalState {
279 | | uint userBalance;
280 | | uint vaultBalance;
281 | | uint marketTokenTotalSupply;
282 | | uint longTokenBalanceMarketVault;
283 | | uint shortTokenBalanceMarketVault;
284 | | uint longTokenBalanceUser;
285 | | uint shortTokenBalanceUser;
286 | | uint simulateLongTokenAmountWithdrawal;
287 | | uint simulateShortTokenAmountWithdrawal;
288 | | uint nativeTokenBalanceUser;
289 | | }
290 | |
291 | | struct MarketData {
292 | | Market.Props marketFromProps;
293 | | Market.Props marketToProps;
294 | | Market.Props marketToUpdate;
295 | | }
296 | |
297 | | struct TokenPrices {
298 | | address[] tokens;
299 | | uint[] maxPrices;
300 | | uint[] minPrices;
301 | | }
302 | |
303 | | // GAMMA Fuzzing helpers
304 | |
305 | | function _logFlow(address vault) internal {
306 | | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow();
307 | | uint flowValue = uint(currentFlow);
308 | |
309 | | if (flowValue == 0) {
310 | | fl.log("EXECUTE ORDER: FLOW NONE");
311 | | } else if (flowValue == 1) {
312 | | fl.log("EXECUTE ORDER: DEPOSIT");
313 | | } else if (flowValue == 2) {
314 | | fl.log("EXECUTE ORDER: SIGNAL_CHANGE");
315 | | } else if (flowValue == 3) {
316 | | fl.log("EXECUTE ORDER: WITHDRAW");
317 | | } else if (flowValue == 4) {
318 | | fl.log("EXECUTE ORDER: COMPOUND");
319 | | } else {
320 | | fl.log("EXECUTE ORDER: UNKNOWN FLOW");
321 | | }
322 | | }
323 | * | function logNextAction(address vault) internal {
324 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
325 | |
326 | * | (
327 | * | PerpetualVault.NextActionSelector selector,
328 | * | bytes memory data
329 | * | ) = perpetualVault.nextAction();
330 | |
331 | * | if (selector == PerpetualVault.NextActionSelector.NO_ACTION) {
332 | * | fl.log("Next action is NO_ACTION");
333 | * | } else if (
334 | * | selector == PerpetualVault.NextActionSelector.INCREASE_ACTION
335 | | ) {
336 | * | fl.log("Next action is INCREASE_ACTION");
337 | * | } else if (selector == PerpetualVault.NextActionSelector.SWAP_ACTION) {
338 | * | fl.log("Next action is SWAP_ACTION");
339 | * | } else if (
340 | * | selector == PerpetualVault.NextActionSelector.WITHDRAW_ACTION
341 | | ) {
342 | * | fl.log("Next action is WITHDRAW_ACTION");
343 | * | } else if (
344 | * | selector == PerpetualVault.NextActionSelector.COMPOUND_ACTION
345 | | ) {
346 | | fl.log("Next action is COMPOUND_ACTION");
347 | * | } else if (
348 | * | selector == PerpetualVault.NextActionSelector.SETTLE_ACTION
349 | | ) {
350 | * | fl.log("Next action is SETTLE_ACTION");
351 | * | } else if (selector == PerpetualVault.NextActionSelector.FINALIZE) {
352 | * | fl.log("Next action is FINALIZE");
353 | | } else {
354 | | fl.log("Unknown next action");
355 | | }
356 | | }
357 | |
358 | * | function _gamma_getVault(
359 | | uint8 seed
360 | * | ) internal returns (address, uint, address, address) {
361 | * | uint256 vaultIndex = seed % 6;
362 | * | if (vaultIndex == 0) {
363 | * | return (
364 | * | vault_GammaVault1x_WETHUSDC,
365 | * | 1,
366 | * | market_WETH_WETH_USDC,
367 | * | gmxUtils_GammaVault1x_WETHUSDC
368 | | );
369 | * | } else if (vaultIndex == 1) {
370 | * | return (
371 | * | vault_GammaVault2x_WETHUSDC,
372 | * | 2,
373 | * | market_WETH_WETH_USDC,
374 | * | gmxUtils_GammaVault2x_WETHUSDC
375 | | );
376 | * | } else if (vaultIndex == 2) {
377 | * | return (
378 | * | vault_GammaVault3x_WETHUSDC,
379 | * | 3,
380 | * | market_WETH_WETH_USDC,
381 | * | gmxUtils_GammaVault3x_WETHUSDC
382 | | );
383 | * | } else if (vaultIndex == 3) {
384 | * | return (
385 | * | vault_GammaVault1x_WBTCUSDC,
386 | * | 1,
387 | * | market_WBTC_WBTC_USDC,
388 | * | gmxUtils_GammaVault1x_WBTCUSDC
389 | | );
390 | * | } else if (vaultIndex == 4) {
391 | * | return (
392 | * | vault_GammaVault2x_WBTCUSDC,
393 | * | 2,
394 | * | market_WBTC_WBTC_USDC,
395 | * | gmxUtils_GammaVault2x_WBTCUSDC
396 | | );
397 | | } else {
398 | * | return (
399 | * | vault_GammaVault3x_WBTCUSDC,
400 | * | 3,
401 | * | market_WBTC_WBTC_USDC,
402 | * | gmxUtils_GammaVault3x_WBTCUSDC
403 | | );
404 | | }
405 | | }
406 | * | function getConvertedMarketPrices(
407 | | address market,
408 | | uint256 priceSeed
409 | * | ) internal returns (MarketPrices memory) {
410 | * | MarketUtils.MarketPrices memory prices = _getMarketPrices(
411 | * | market,
412 | * | _setTokenPrices(priceSeed)
413 | | );
414 | |
415 | * | MarketPrices memory convertedPrices = MarketPrices({
416 | * | indexTokenPrice: PriceProps({
417 | * | min: prices.indexTokenPrice.min,
418 | * | max: prices.indexTokenPrice.max
419 | | }),
420 | * | longTokenPrice: PriceProps({
421 | * | min: prices.longTokenPrice.min,
422 | * | max: prices.longTokenPrice.max
423 | | }),
424 | * | shortTokenPrice: PriceProps({
425 | * | min: prices.shortTokenPrice.min,
426 | * | max: prices.shortTokenPrice.max
427 | | })
428 | | });
429 | |
430 | * | return convertedPrices;
431 | | }
432 | * | function _getRandomDepositId(
433 | | uint8 seed,
434 | | address user,
435 | | address vault
436 | * | ) internal view returns (uint256) {
437 | * | uint256[] memory depositIds = PerpetualVault(vault).getUserDeposits(
438 | * | user
439 | | );
440 | |
441 | *r | require(depositIds.length > 0, "No deposits found for the user");
442 | |
443 | * | if (depositIds.length == 1) {
444 | * | return depositIds[0];
445 | | }
446 | |
447 | * | uint256 randomIndex = seed % depositIds.length;
448 | * | return depositIds[randomIndex];
449 | | }
450 | |
451 | *r | function constructSwapCalldata(
452 | | address tokenIn,
453 | | address tokenOut,
454 | | uint256 amountIn,
455 | | uint256 amountOutMin,
456 | | address vault
457 | * | ) public returns (bytes memory) {
458 | | // Allocate memory for swapCalldata (4 + 7 * 32 = 228 bytes)
459 | * | bytes memory swapCalldata = new bytes(228);
460 | * | bytes4 selector = 0x89fe039b;
461 | |
462 | * | assembly {
463 | | // Get the pointer to the free memory
464 | * | let ptr := add(swapCalldata, 32)
465 | | // Store the function selector in the first 4 bytes
466 | * | mstore(ptr, selector)
467 | | // Store tokenIn
468 | * | mstore(add(ptr, 4), tokenIn) //from token
469 | | // Store tokenOut
470 | * | mstore(add(ptr, 36), tokenOut) //to token
471 | | // Store amountIn
472 | * | mstore(add(ptr, 68), amountIn)
473 | | // Store amountOutMin
474 | * | mstore(add(ptr, 100), amountOutMin)
475 | | // Store placeholder address(0)
476 | * | mstore(add(ptr, 132), 0)
477 | | // Store placeholder address(0)
478 | * | mstore(add(ptr, 164), vault) //to 196
479 | | }
480 | |
481 | | // Construct the data for _doDexSwap
482 | * | bytes memory dexSwapData = abi.encode(
483 | * | PARASWAP_ROUTER,
484 | * | amountIn,
485 | * | swapCalldata
486 | | );
487 | |
488 | | // Construct the final calldata for _runSwap
489 | * | bytes memory finalCalldata = abi.encode(PROTOCOL.DEX, dexSwapData);
490 | |
491 | * | address valueAt196;
492 | | assembly {
493 | * | valueAt196 := mload(add(swapCalldata, 196))
494 | | }
495 | |
496 | * | return finalCalldata;
497 | | }
498 | |
499 | * | function constructGMXCalldata(
500 | | uint8 seed,
501 | | uint256 amountIn
502 | * | ) internal returns (bytes memory finalCalldata) {
503 | * | address[] memory gmxpath = _getSwapPath(seed);
504 | * | bytes memory dexSwapData = abi.encode(gmxpath, amountIn, 0); //min output amount hardcoded at 0
505 | * | finalCalldata = abi.encode(PROTOCOL.GMX, dexSwapData);
506 | | }
507 | |
508 | *r | function getPositionCollateral(
509 | | address vault
510 | * | ) public returns (uint collateralAmount) {
511 | *r | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
512 | * | ReaderUtils.PositionInfo memory positionInfo = reader
513 | | .getPositionInfo(
514 | * | dataStore,
515 | * | referralStorage,
516 | * | PerpetualVault(vault).curPositionKey(),
517 | * | _getMarketPrices(
518 | * | vaultToMarket[vault],
519 | * | _setTokenPrices(5000e4)
520 | | ), //any price, checking for collateral
521 | * | uint256(0),
522 | * | address(0),
523 | * | true
524 | | );
525 | |
526 | * | collateralAmount = positionInfo.position.numbers.collateralAmount;
527 | | }
528 | | }
529 | |
530 | * | function checkNextAction(address vault) public view returns (bool isLong) {
531 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
532 | |
533 | *r | (, bytes memory data) = perpetualVault.nextAction();
534 | |
535 | * | (isLong, ) = abi.decode(data, (bool, uint256));
536 | | }
537 | |
538 | * | function isNextNoAction(
539 | | address vault
540 | * | ) public view returns (bool isNoAction) {
541 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
542 | |
543 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault
544 | | .nextAction();
545 | |
546 | * | if (selector == PerpetualVault.NextActionSelector.NO_ACTION) {
547 | * | return true;
548 | | }
549 | * | return false;
550 | | }
551 | |
552 | * | function isNextFinalize(
553 | | address vault
554 | * | ) public view returns (bool isFinalize) {
555 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
556 | |
557 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault
558 | | .nextAction();
559 | |
560 | * | if (selector == PerpetualVault.NextActionSelector.FINALIZE) {
561 | * | return true;
562 | | }
563 | * | return false;
564 | | }
565 | * | function isNextSettle(address vault) public view returns (bool isSettle) {
566 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
567 | |
568 | * | (PerpetualVault.NextActionSelector selector, ) = perpetualVault
569 | | .nextAction();
570 | |
571 | * | if (selector == PerpetualVault.NextActionSelector.SETTLE_ACTION) {
572 | * | return true;
573 | | }
574 | * | return false;
575 | | }
576 | |
577 | * | function isNextWithdraw(
578 | | address vault
579 | * | ) public view returns (bool isFinalize) {
580 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
581 | |
582 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault
583 | | .nextAction();
584 | |
585 | * | if (selector == PerpetualVault.NextActionSelector.WITHDRAW_ACTION) {
586 | * | return true;
587 | | }
588 | * | return false;
589 | | }
590 | * | function isNextSwap(address vault) public view returns (bool isSwap) {
591 | * | PerpetualVault perpetualVault = PerpetualVault(vault);
592 | |
593 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault
594 | | .nextAction();
595 | |
596 | * | if (selector == PerpetualVault.NextActionSelector.SWAP_ACTION) {
597 | * | return true;
598 | | }
599 | * | return false;
600 | | }
601 | | // GMX Fuzzing helpers
602 | |
603 | | // Percentage diff inspired by EBTC suite
604 | | //https://github.com/ebtc-protocol/ebtc/blob/3406f0d88ac9935da53f7371fb078d11c066802e/packages/contracts/contracts/TestContracts/invariants/Asserts.sol#L31
605 | * | function eqPercentageDiff(
606 | | uint256 a,
607 | | uint256 b,
608 | | uint256 maxPercentDiff,
609 | | string memory reason
610 | * | ) internal {
611 | * | uint256 percentDiff;
612 | |
613 | * | if (a == b) return;
614 | |
615 | * | if (a > b) {
616 | * | percentDiff = ((a - b) * 1e30) / ((a + b) / 2);
617 | | } else {
618 | * | percentDiff = ((b - a) * 1e30) / ((a + b) / 2);
619 | | }
620 | |
621 | * | if (percentDiff > maxPercentDiff) {
622 | | fl.log("a>b, a: ", a);
623 | | fl.log("a>b, b:", b);
624 | | fl.log(
625 | | "Percentage difference is bigger than expected",
626 | | percentDiff
627 | | );
628 | | fl.t(false, reason);
629 | | } else {
630 | * | fl.t(true, "Invariant ok, ckeched for: ");
631 | * | fl.log(reason);
632 | * | fl.log("Percentage difference: ", percentDiff);
633 | | }
634 | | }
635 | |
636 | | //General utils
637 | |
638 | * | function _setTokenPrices(
639 | | uint priceSeed
640 | * | ) internal returns (TokenPrices memory) {
641 | * | address[] memory tokens = new address[](5);
642 | * | uint[] memory maxPrices = new uint[](5);
643 | * | uint[] memory minPrices = new uint[](5);
644 | |
645 | * | tokens[0] = address(WETH);
646 | * | tokens[1] = address(WBTC);
647 | * | tokens[2] = address(USDT);
648 | * | tokens[3] = address(USDC);
649 | * | tokens[4] = address(SOL);
650 | |
651 | * | for (uint i = 0; i < tokens.length; i++) {
652 | * | (minPrices[i], maxPrices[i]) = _getTokenPrices(
653 | * | tokens[i],
654 | * | priceSeed
655 | | );
656 | | }
657 | |
658 | * | TokenPrices memory tokenPrices = TokenPrices({
659 | * | tokens: tokens,
660 | * | maxPrices: maxPrices,
661 | * | minPrices: minPrices
662 | | });
663 | |
664 | * | return tokenPrices;
665 | | }
666 | * | function _getTokenPrices(
667 | | address token,
668 | | uint256 price
669 | * | ) internal returns (uint256 minPrice, uint256 maxPrice) {
670 | * | tokenMinPrice[address(WETH)] = WETH_MIN_PRICE;
671 | * | tokenMinPrice[address(WBTC)] = WBTC_MIN_PRICE;
672 | * | tokenMinPrice[address(USDT)] = USDT_MIN_PRICE;
673 | * | tokenMinPrice[address(USDC)] = USDC_MIN_PRICE;
674 | * | tokenMinPrice[address(SOL)] = SOL_MIN_PRICE;
675 | |
676 | * | tokenMaxPrice[address(WETH)] = WETH_MAX_PRICE;
677 | * | tokenMaxPrice[address(WBTC)] = WBTC_MAX_PRICE;
678 | * | tokenMaxPrice[address(USDT)] = USDT_MAX_PRICE;
679 | * | tokenMaxPrice[address(USDC)] = USDC_MAX_PRICE;
680 | * | tokenMaxPrice[address(SOL)] = SOL_MAX_PRICE;
681 | |
682 | * | minPrice = clampBetween(
683 | * | price,
684 | * | tokenMinPrice[token],
685 | * | tokenMaxPrice[token]
686 | | );
687 | |
688 | * | maxPrice = clampBetween(
689 | * | price,
690 | * | tokenMinPrice[token],
691 | * | tokenMaxPrice[token]
692 | | );
693 | |
694 | * | if (minPrice > maxPrice) {
695 | | (minPrice, maxPrice) = (maxPrice, minPrice);
696 | | }
697 | | }
698 | |
699 | * | function _getTokenPrice(
700 | | address token,
701 | | TokenPrices memory tokenPrices
702 | * | ) internal returns (uint) {
703 | | //RETURNS MAX PRICE
704 | * | for (uint i = 0; i < tokenPrices.tokens.length; i++) {
705 | * | if (tokenPrices.tokens[i] == token) {
706 | * | return tokenPrices.maxPrices[i] * (10 ** _getPrecision(token));
707 | | }
708 | | }
709 | |
710 | | revert("Token was not found");
711 | | }
712 | |
713 | * | function _getTokenAmounts(
714 | | uint longAmount,
715 | | uint shortAmount,
716 | | address longToken,
717 | | address shortToken,
718 | | address user
719 | * | ) internal returns (uint longAmountClamped, uint shortAmountClamped) {
720 | * | tokenMaxAmounts[address(WETH)] = address(user).balance;
721 | * | tokenMaxAmounts[address(WBTC)] = WBTC_MAX_AMOUNT;
722 | * | tokenMaxAmounts[address(USDT)] = USDT_MAX_AMOUNT;
723 | * | tokenMaxAmounts[address(USDC)] = USDC_MAX_AMOUNT;
724 | * | tokenMaxAmounts[address(SOL)] = SOL_MAX_AMOUNT;
725 | |
726 | * | tokenMinAmounts[address(WETH)] = WETH_MIN_AMOUNT;
727 | * | tokenMinAmounts[address(WBTC)] = WBTC_MIN_AMOUNT;
728 | * | tokenMinAmounts[address(USDT)] = USDT_MIN_AMOUNT;
729 | * | tokenMinAmounts[address(USDC)] = USDC_MIN_AMOUNT;
730 | * | tokenMinAmounts[address(SOL)] = SOL_MIN_AMOUNT;
731 | |
732 | * | longAmountClamped = clampBetween(
733 | * | longAmount,
734 | * | tokenMinAmounts[longToken],
735 | * | tokenMaxAmounts[longToken]
736 | | );
737 | * | shortAmountClamped = clampBetween(
738 | * | shortAmount,
739 | * | tokenMinAmounts[shortToken],
740 | * | tokenMaxAmounts[shortToken]
741 | | );
742 | | }
743 | |
744 | | /**Lib functions */
745 | |
746 | | function _getPoolAmount(
747 | | DataStore dataStore,
748 | | Market.Props memory market,
749 | | address token
750 | | ) internal view returns (uint256) {
751 | | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
752 | | return
753 | | dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) /
754 | | divisor;
755 | | }
756 | | function getPoolDivisor(
757 | | address longToken,
758 | | address shortToken
759 | | ) internal pure returns (uint256) {
760 | | return longToken == shortToken ? 2 : 1;
761 | | }
762 | | /*
763 | | *HELPERS
764 | | *
765 | | */
766 | |
767 | | function _getClaimableFeeAmount(
768 | | address market,
769 | | address token
770 | | ) internal returns (uint) {
771 | | bytes32 CLAIMABLE_FEE_AMOUNT = keccak256(
772 | | abi.encode("CLAIMABLE_FEE_AMOUNT")
773 | | );
774 | | bytes32 key = keccak256(
775 | | abi.encode(CLAIMABLE_FEE_AMOUNT, market, token)
776 | | );
777 | | uint256 feeAmount = dataStore.getUint(key);
778 | | }
779 | |
780 | * | function _getRandomUser(uint8 input) internal returns (address) {
781 | * | uint256 randomIndex = input % USERS.length;
782 | * | return USERS[randomIndex];
783 | | }
784 | |
785 | * | function _getMarketAddress(uint8 index) internal view returns (address) {
786 | * | uint256 marketIndex = index % 6;
787 | |
788 | * | if (marketIndex == 0) {
789 | * | return market_WETH_WETH_USDC;
790 | * | } else if (marketIndex == 1) {
791 | * | return market_WETH_WETH_USDT;
792 | * | } else if (marketIndex == 2) {
793 | * | return market_0_WETH_USDC;
794 | | } else {
795 | * | return market_WBTC_WBTC_USDC;
796 | | }
797 | | }
798 | |
799 | * | function _getRandomToken(uint8 index) internal view returns (address) {
800 | * | uint tokenIndex = index % 4;
801 | |
802 | * | if (tokenIndex == 0) {
803 | * | return address(USDC);
804 | * | } else if (tokenIndex == 1) {
805 | * | return address(WBTC);
806 | * | } else if (tokenIndex == 2) {
807 | * | return address(USDT);
808 | | } else {
809 | * | return address(WETH);
810 | | }
811 | | }
812 | |
813 | * | function _getMarketPrices(
814 | | address marketToUpdate,
815 | | TokenPrices memory tokenPrices
816 | * | ) internal returns (MarketUtils.MarketPrices memory prices) {
817 | * | Market.Props memory marketProps = MarketStoreUtils.get(
818 | * | dataStore,
819 | * | marketToUpdate
820 | | );
821 | |
822 | * | Price.Props memory indexTokenPrice;
823 | * | Price.Props memory longTokenPrice;
824 | * | Price.Props memory shortTokenPrice;
825 | |
826 | * | for (uint256 i = 0; i < tokenPrices.tokens.length; i++) {
827 | * | if (tokenPrices.tokens[i] == marketProps.indexToken) {
828 | * | indexTokenPrice = Price.Props({
829 | * | min: tokenPrices.minPrices[i] *
830 | * | (10 ** _getPrecision(marketProps.indexToken)),
831 | * | max: tokenPrices.maxPrices[i] *
832 | * | (10 ** _getPrecision(marketProps.indexToken))
833 | | });
834 | | }
835 | |
836 | * | if (tokenPrices.tokens[i] == marketProps.longToken) {
837 | * | longTokenPrice = Price.Props({
838 | * | min: tokenPrices.minPrices[i] *
839 | * | (10 ** _getPrecision(marketProps.longToken)),
840 | * | max: tokenPrices.maxPrices[i] *
841 | * | (10 ** _getPrecision(marketProps.longToken))
842 | | });
843 | | }
844 | |
845 | * | if (tokenPrices.tokens[i] == marketProps.shortToken) {
846 | * | shortTokenPrice = Price.Props({
847 | * | min: tokenPrices.minPrices[i] *
848 | * | (10 ** _getPrecision(marketProps.shortToken)),
849 | * | max: tokenPrices.maxPrices[i] *
850 | * | (10 ** _getPrecision(marketProps.shortToken))
851 | | });
852 | | }
853 | | }
854 | |
855 | * | return
856 | * | MarketUtils.MarketPrices({
857 | * | indexTokenPrice: indexTokenPrice,
858 | * | longTokenPrice: longTokenPrice,
859 | * | shortTokenPrice: shortTokenPrice
860 | | });
861 | | }
862 | |
863 | * | function _getPrecision(address token) internal view returns (uint256) {
864 | * | if (token == address(WETH)) {
865 | * | return 8;
866 | * | } else if (token == address(WBTC)) {
867 | * | return 20;
868 | * | } else if (token == address(USDC) || token == address(USDT)) {
869 | * | return 18;
870 | * | } else if (token == address(SOL)) {
871 | * | return 17;
872 | | }
873 | | revert("Unsupported token");
874 | | }
875 | |
876 | | function _getMarketDataBeforeAfter(
877 | | ShiftUtils.CreateShiftParams memory createShiftParams,
878 | | TokenPrices memory tokenPrices,
879 | | bool isAfterShift,
880 | | uint marketTokenAmountToShift
881 | | ) internal returns (ShiftMarketData memory data) {
882 | | Market.Props memory marketFrom = MarketStoreUtils.get(
883 | | dataStore,
884 | | createShiftParams.fromMarket
885 | | );
886 | | Market.Props memory marketToUpdate = MarketStoreUtils.get(
887 | | dataStore,
888 | | createShiftParams.toMarket
889 | | );
890 | |
891 | | (data.marketTokenPriceFrom, ) = MarketUtils.getMarketTokenPrice(
892 | | dataStore,
893 | | marketFrom,
894 | | _getMarketPrices(marketFrom.marketToken, tokenPrices)
895 | | .indexTokenPrice,
896 | | _getMarketPrices(marketFrom.marketToken, tokenPrices)
897 | | .longTokenPrice,
898 | | _getMarketPrices(marketFrom.marketToken, tokenPrices)
899 | | .shortTokenPrice,
900 | | keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS")),
901 | | false
902 | | );
903 | |
904 | | (data.marketTokenPriceTo, ) = MarketUtils.getMarketTokenPrice(
905 | | dataStore,
906 | | marketToUpdate,
907 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices)
908 | | .indexTokenPrice,
909 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices)
910 | | .longTokenPrice,
911 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices)
912 | | .shortTokenPrice,
913 | | keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS")),
914 | | false
915 | | );
916 | |
917 | | Market.Props memory marketForWithdrawal = isAfterShift
918 | | ? marketToUpdate
919 | | : marketFrom;
920 | |
921 | | if (!isAfterShift) {
922 | | (
923 | | data.simulateLongTokenAmountWithdrawal,
924 | | data.simulateShortTokenAmountWithdrawal
925 | | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut(
926 | | dataStore,
927 | | marketForWithdrawal,
928 | | _getMarketPrices(marketForWithdrawal.marketToken, tokenPrices),
929 | | marketTokenAmountToShift,
930 | | address(0),
931 | | ISwapPricingUtils.SwapPricingType.Shift
932 | | );
933 | | } else {
934 | | (
935 | | data.simulateLongTokenAmountWithdrawal,
936 | | data.simulateShortTokenAmountWithdrawal
937 | | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut(
938 | | dataStore,
939 | | marketForWithdrawal,
940 | | _getMarketPrices(marketForWithdrawal.marketToken, tokenPrices),
941 | | ERC20(marketForWithdrawal.marketToken).balanceOf(
942 | | address(createShiftParams.receiver)
943 | | ),
944 | | address(0),
945 | | ISwapPricingUtils.SwapPricingType.Shift
946 | | );
947 | | }
948 | | }
949 | |
950 | * | function _getSwapPath(uint8 seed) internal returns (address[] memory) {
951 | * | address[] memory markets = new address[](4);
952 | * | markets[0] = address(market_0_WETH_USDC);
953 | * | markets[1] = address(market_WBTC_WBTC_USDC);
954 | * | markets[2] = address(market_WETH_WETH_USDC);
955 | * | markets[3] = address(market_WETH_WETH_USDT);
956 | |
957 | * | if (seed == 0) {
958 | | //get some valid path
959 | * | address[] memory path = new address[](2);
960 | * | path[0] = address(market_WETH_WETH_USDC);
961 | * | path[1] = address(market_0_WETH_USDC);
962 | * | return path;
963 | * | } else if (seed == 7) {
964 | * | return new address[](0); //return empty array on specific seed
965 | | } else {
966 | * | uint numMarkets = seed % (markets.length + 1);
967 | * | address[] memory path = new address[](numMarkets);
968 | * | for (uint i = 0; i < numMarkets; i++) {
969 | * | uint index = (seed + i) % (markets.length - i);
970 | * | path[i] = markets[index];
971 | |
972 | * | markets[index] = markets[markets.length - 1 - i];
973 | | }
974 | * | return path;
975 | | }
976 | | }
977 | |
978 | * | function _getTokenOut(
979 | | address[] memory swapPath,
980 | | address inputToken
981 | * | ) internal returns (address[] memory, address) {
982 | * | if (swapPath.length == 0) {
983 | * | return (new address[](0), inputToken);
984 | | }
985 | |
986 | * | address currentToken = inputToken;
987 | * | bool isValidPath = true;
988 | |
989 | * | for (uint i = 0; i < swapPath.length; i++) {
990 | * | Market.Props memory market = MarketStoreUtils.get(
991 | * | dataStore,
992 | * | swapPath[i]
993 | | );
994 | |
995 | * | if (currentToken == market.longToken) {
996 | * | currentToken = market.shortToken;
997 | * | } else if (currentToken == market.shortToken) {
998 | * | currentToken = market.longToken;
999 | | } else {
1000 | | // Invalid market for the current token
1001 | * | isValidPath = false;
1002 | * | break;
1003 | | }
1004 | | }
1005 | |
1006 | * | if (!isValidPath) {
1007 | * | return (new address[](0), address(0));
1008 | | }
1009 | |
1010 | * | return (swapPath, currentToken);
1011 | | }
1012 | |
1013 | * | function _getAmountsOut(
1014 | | address[] memory marketPath,
1015 | | address inputToken,
1016 | | uint256 amountIn,
1017 | | address uiFeeReceiver,
1018 | | TokenPrices memory tokenPrices
1019 | * | ) internal returns (SwapResult memory) {
1020 | * | GetAmountsOutCache memory cache;
1021 | * | SwapResult memory result;
1022 | |
1023 | * | if (marketPath.length == 0) {
1024 | * | result.amountOut = amountIn;
1025 | * | return result;
1026 | | }
1027 | |
1028 | * | cache.currentToken = inputToken;
1029 | * | cache.currentAmount = amountIn;
1030 | |
1031 | * | for (uint256 i = 0; i < marketPath.length; i++) {
1032 | * | cache.market = MarketStoreUtils.get(dataStore, marketPath[i]);
1033 | * | cache.prices = _getMarketPrices(marketPath[i], tokenPrices);
1034 | |
1035 | * | (
1036 | * | uint256 stepAmountOut,
1037 | * | int256 stepImpactAmount,
1038 | * | SwapPricingUtils.SwapFees memory stepFees
1039 | *r | ) = reader.getSwapAmountOut(
1040 | * | dataStore, // DataStore dataStore,
1041 | * | cache.market, // Market.Props memory market,
1042 | * | cache.prices, // MarketUtils.MarketPrices memory prices,
1043 | * | cache.currentToken, // address tokenIn,
1044 | * | cache.currentAmount, // uint256 amountIn,
1045 | * | cache.uiFeeReceiver // address uiFeeReceiver
1046 | | );
1047 | |
1048 | * | cache.currentToken = (cache.currentToken == cache.market.longToken)
1049 | * | ? cache.market.shortToken
1050 | * | : cache.market.longToken;
1051 | * | cache.currentAmount = stepAmountOut;
1052 | |
1053 | * | result.totalImpactAmount += stepImpactAmount;
1054 | * | result.totalFees.feeAmountForPool += stepFees.feeAmountForPool;
1055 | * | result.totalFees.feeReceiverAmount += stepFees.feeReceiverAmount;
1056 | * | result.totalFees.uiFeeAmount += stepFees.uiFeeAmount;
1057 | * | result.amountOut = cache.currentAmount;
1058 | | }
1059 | |
1060 | | // result.amountAfterFees = stepFees.amountAfterFees;
1061 | * | return result;
1062 | | }
1063 | |
1064 | | function _getRandomTokenPair(
1065 | | uint seed,
1066 | | address addressTo
1067 | | ) internal view returns (address, address) {
1068 | | if (
1069 | | addressTo == market_0_WETH_USDC ||
1070 | | addressTo == market_WETH_WETH_USDC
1071 | | ) {
1072 | | return (address(WETH), address(USDC));
1073 | | } else if (addressTo == market_WBTC_WBTC_USDC) {
1074 | | return (address(WBTC), address(USDC));
1075 | | } else if (addressTo == market_WETH_WETH_USDC) {
1076 | | return (address(WETH), address(USDC));
1077 | | } else if (addressTo == market_WETH_WETH_USDT) {
1078 | | return (address(WETH), address(USDT));
1079 | | } else {
1080 | | address[4] memory tokens = [
1081 | | address(WETH),
1082 | | address(WBTC),
1083 | | address(USDC),
1084 | | address(USDT)
1085 | | ];
1086 | | uint randomLongToken = seed % tokens.length;
1087 | | uint randomShortToken = seed % tokens.length;
1088 | | return (tokens[randomLongToken], tokens[randomShortToken]);
1089 | | }
1090 | | }
1091 | |
1092 | | //@author Rappie from Perimetersec
1093 | * | function clampBetween(
1094 | | uint256 value,
1095 | | uint256 low,
1096 | | uint256 high
1097 | * | ) internal returns (uint256) {
1098 | * | if (value < low || value > high) {
1099 | * | uint256 ans = low + (value % (high - low + 1));
1100 | |
1101 | * | return ans;
1102 | | }
1103 | * | return value;
1104 | | }
1105 | |
1106 | | //@author Rappie from Perimetersec
1107 | | bytes16 internal constant HEX_DIGITS = "0123456789abcdef";
1108 | |
1109 | * | function toHexString(
1110 | | bytes memory value
1111 | * | ) internal pure returns (string memory) {
1112 | * | bytes memory buffer = new bytes(2 * value.length + 2);
1113 | * | buffer[0] = "0";
1114 | * | buffer[1] = "x";
1115 | * | for (uint256 i = 0; i < value.length; i++) {
1116 | * | uint8 valueByte = uint8(value[i]);
1117 | * | buffer[2 * i + 2] = HEX_DIGITS[valueByte >> 4];
1118 | * | buffer[2 * i + 3] = HEX_DIGITS[valueByte & 0xf];
1119 | | }
1120 | * | return string(buffer);
1121 | | }
1122 | * | function abs(int256 x) internal pure returns (uint256) {
1123 | * | return x >= 0 ? uint256(x) : uint256(-x);
1124 | | }
1125 | | }
1126 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/DonationSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./PropertiesSetup.sol";
6 | |
7 | | contract DonationSetup is PropertiesSetup {
8 | | //turned off
9 | | function Donate(
10 | | uint seed,
11 | | uint8 userSeed,
12 | | address addressFrom,
13 | | uint longAmount,
14 | | uint shortAmount
15 | | ) internal {
16 | | uint userIndex = seed % USERS.length;
17 | | addressFrom = _getRandomUser(userSeed);
18 | |
19 | | address addressTo;
20 | | uint randomAddress = seed % 10;
21 | | if (randomAddress == 0) {
22 | | addressTo = address(depositVault);
23 | | } else if (randomAddress == 1) {
24 | | addressTo = address(orderVault);
25 | | } else if (randomAddress == 2) {
26 | | addressTo = address(shiftVault);
27 | | } else if (randomAddress == 3) {
28 | | addressTo = address(withdrawalVault);
29 | | } else if (randomAddress == 4) {
30 | | addressTo = market_0_WETH_USDC;
31 | | } else if (randomAddress == 6) {
32 | | addressTo = market_WBTC_WBTC_USDC;
33 | | } else if (randomAddress == 8) {
34 | | addressTo = market_WETH_WETH_USDC;
35 | | } else {
36 | | addressTo = market_WETH_WETH_USDT;
37 | | }
38 | |
39 | | (address longToken, address shortToken) = _getRandomTokenPair(
40 | | seed,
41 | | addressTo
42 | | );
43 | |
44 | | bool isWeth = longToken == address(WETH) || shortToken == address(WETH);
45 | |
46 | | (uint longAmountClamped, uint shortAmountClamped) = _getTokenAmounts(
47 | | longAmount,
48 | | shortAmount,
49 | | longToken,
50 | | shortToken,
51 | | addressFrom
52 | | );
53 | |
54 | | _mintAndSendTokensTo(
55 | | addressFrom,
56 | | addressTo,
57 | | longAmountClamped,
58 | | shortAmountClamped,
59 | | longToken,
60 | | shortToken,
61 | | 0,
62 | | isWeth
63 | | );
64 | | }
65 | | }
66 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/GMXSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./depositSetup/DepositSpeedup.sol";
5 | | import "./withdrawSetup/WithdrawSpeedup.sol";
6 | | import "./positionSetup/PositionSpeedup.sol";
7 | | import "./positionSetup/GMXPositionSpeedup.sol";
8 | | import "./shiftSetup/ShiftSpeedup.sol";
9 | | import "./LiquidationSetup.sol";
10 | | import "./DonationSetup.sol";
11 | |
12 | | contract GMXSetup is
13 | | DepositSpeedup,
14 | | WithdrawSpeedup,
15 | | PositionSpeedup,
16 | | GMXPositionSpeedup,
17 | | ShiftSpeedup,
18 | | LiquidationSetup,
19 | | DonationSetup
20 | | //ADL is imported through positions contract
21 | | {
22 | | function SetUpGMX() internal {
23 | | deployment(address(this));
24 | | marketsSetup();
25 | | userSetup();
26 | | deployCallbackCotracts();
27 | | deployGammaVault1x_WETHUSDC();
28 | | deployGammaVault2x_WETHUSDC();
29 | | deployGammaVault3x_WETHUSDC();
30 | | deployGammaVault1x_WBTCUSDC();
31 | | deployGammaVault2x_WBTCUSDC();
32 | | deployGammaVault3x_WBTCUSDC();
33 | | setVaultsArray();
34 | | deployDex();
35 | |
36 | | for (uint i = 0; i < USERS.length; ++i) {
37 | | if (address(USERS[i]).balance > 0) {
38 | | vm.prank(USERS[i]);
39 | | WETH.deposit{value: address(USERS[i]).balance / 2}();
40 | | }
41 | | MintableToken(address(USDC)).mint(USERS[i], 1000_000_000e6);
42 | | MintableToken(address(USDT)).mint(USERS[i], 1000_000_000e6);
43 | | MintableToken(address(WBTC)).mint(USERS[i], 1_000_000e8);
44 | | }
45 | |
46 | | if (address(paraswapDeployer).balance > 0) {
47 | | uint paraswapDeployerBalance = address(paraswapDeployer).balance;
48 | | vm.prank(paraswapDeployer);
49 | | WETH.deposit{value: paraswapDeployerBalance / 2}();
50 | | }
51 | | MintableToken(address(USDC)).mint(paraswapDeployer, 1000_000_000e6);
52 | | MintableToken(address(USDT)).mint(paraswapDeployer, 1000_000_000e6);
53 | | MintableToken(address(WBTC)).mint(paraswapDeployer, 1_000_000e8);
54 | |
55 | | setUpDeposits(6, 500e18, 100_000_000e6);
56 | | setUpDeposits(7, 500e18, 100_000_000e6);
57 | | setUpDeposits(8, 500e18, 100_000_000e6);
58 | | setUpDeposits(9, 500e8, 100_000_000e6);
59 | |
60 | | addLiquidityDex();
61 | | fillVaultMarketMap();
62 | | setRouterInVault();
63 | | }
64 | |
65 | | /**
66 | | *
67 | | * GAMMA GUIDED FUNCTIONS
68 | | *
69 | | */
70 | |
71 | *r | function fuzz_GammaDepositWithOpenPosition(
72 | | uint8 seed,
73 | | uint8 userSeed,
74 | | uint priceSeed
75 | * | ) public {
76 | * | (address vault, , , ) = _gamma_getVault(seed);
77 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
78 | |
79 | * | IncreaseOrder(seed, priceSeed, true);
80 | * | ExecuteOrder(seed, priceSeed, false);
81 | |
82 | * | GammaDeposit(seed, userSeed, priceSeed);
83 | * | NextActionPerps(seed, priceSeed);
84 | * | ExecuteOrder(seed, priceSeed, false);
85 | |
86 | * | NextActionPerps(seed, priceSeed);
87 | |
88 | * | address user = _getRandomUser(userSeed);
89 | |
90 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
91 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
92 | * | } else if (isNextFinalize(vault)) {
93 | | NextActionPerps(seed, priceSeed);
94 | | }
95 | * | if (
96 | * | initialFlow == PerpetualVault.FLOW.NONE &&
97 | * | !PerpetualVaultLens(vault).cancellationTriggered()
98 | | ) {
99 | * | gammaGeneralPostconditions(vault, priceSeed);
100 | | }
101 | * | _invariant_GAMMA_12(vault, user);
102 | | }
103 | |
104 | *r | function fuzz_GammaWithdrawWithOpenPosition(
105 | | uint8 seed,
106 | | uint8 userSeed,
107 | | uint priceSeed
108 | * | ) public {
109 | * | (address vault, , , ) = _gamma_getVault(seed);
110 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
111 | * | IncreaseOrder(seed, priceSeed, true);
112 | * | ExecuteOrder(seed, priceSeed, false);
113 | |
114 | * | GammaWithdraw(seed, userSeed, priceSeed);
115 | * | ExecuteOrder(seed, priceSeed, false);
116 | |
117 | * | NextActionPerps(seed, priceSeed);
118 | * | ExecuteOrder(seed, priceSeed, false);
119 | * | NextActionPerps(seed, priceSeed);
120 | |
121 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
122 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
123 | * | } else if (isNextFinalize(vault)) {
124 | | NextActionPerps(seed, priceSeed);
125 | | }
126 | * | if (
127 | * | initialFlow == PerpetualVault.FLOW.NONE &&
128 | * | !PerpetualVaultLens(vault).cancellationTriggered()
129 | | ) {
130 | * | gammaGeneralPostconditions(vault, priceSeed);
131 | | }
132 | | }
133 | |
134 | *r | function fuzz_GammaOpenPosition1x(
135 | | bool isLong,
136 | | bool isParaswap,
137 | | uint8 seed,
138 | | uint8 userSeed,
139 | | uint priceSeed,
140 | | uint amount
141 | * | ) public {
142 | * | (address vault, , , ) = _gamma_getVault(seed);
143 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
144 | |
145 | * | SwapOrder(
146 | * | isLong,
147 | * | isParaswap, //only paraswap
148 | * | seed,
149 | * | priceSeed,
150 | * | amount
151 | | );
152 | * | ExecuteOrder(seed, priceSeed, false);
153 | |
154 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
155 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
156 | * | } else if (isNextFinalize(vault)) {
157 | * | NextActionPerps(seed, priceSeed);
158 | | }
159 | * | if (
160 | * | initialFlow == PerpetualVault.FLOW.NONE &&
161 | * | !PerpetualVaultLens(vault).cancellationTriggered()
162 | | ) {
163 | * | gammaGeneralPostconditions(vault, priceSeed);
164 | | }
165 | | }
166 | |
167 | *r | function fuzz_GammaSwitchPositionType(
168 | | uint8 seed,
169 | | uint8 userSeed,
170 | | uint priceSeed
171 | * | ) public {
172 | * | (address vault, , , ) = _gamma_getVault(seed);
173 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
174 | |
175 | * | IncreaseOrder(seed, priceSeed, true); // Open long
176 | * | ExecuteOrder(seed, priceSeed, false);
177 | |
178 | * | IncreaseOrder(seed, priceSeed, false); // Attempt to open short
179 | * | ExecuteOrder(seed, priceSeed, false); // This should close the long position
180 | |
181 | * | NextActionPerps(seed, priceSeed);
182 | |
183 | * | IncreaseOrder(seed, priceSeed, false); // Attempt to open short
184 | * | ExecuteOrder(seed, priceSeed, false); // This should close the long position
185 | |
186 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
187 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
188 | * | } else if (isNextFinalize(vault)) {
189 | | NextActionPerps(seed, priceSeed);
190 | | }
191 | * | if (
192 | * | initialFlow == PerpetualVault.FLOW.NONE &&
193 | * | !PerpetualVaultLens(vault).cancellationTriggered()
194 | | ) {
195 | * | gammaGeneralPostconditions(vault, priceSeed);
196 | | }
197 | | }
198 | |
199 | *r | function fuzz_GammaCloseNonOneLeveragePosition(
200 | | uint8 seed,
201 | | uint8 userSeed,
202 | | uint priceSeed
203 | * | ) public {
204 | * | (address vault, , , ) = _gamma_getVault(seed);
205 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
206 | |
207 | * | IncreaseOrder(seed, priceSeed, true);
208 | * | ExecuteOrder(seed, priceSeed, false);
209 | |
210 | * | DecreasePosition(seed, priceSeed, true);
211 | * | ExecuteOrder(seed, priceSeed, false);
212 | |
213 | * | NextActionPerps(seed, priceSeed);
214 | |
215 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
216 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
217 | * | } else if (isNextFinalize(vault)) {
218 | | NextActionPerps(seed, priceSeed);
219 | | }
220 | * | if (
221 | * | initialFlow == PerpetualVault.FLOW.NONE &&
222 | * | !PerpetualVaultLens(vault).cancellationTriggered()
223 | | ) {
224 | * | gammaGeneralPostconditions(vault, priceSeed);
225 | | }
226 | | }
227 | |
228 | *r | function fuzz_GammaCloseOneLeveragePosition(
229 | | uint8 seed,
230 | | uint8 userSeed,
231 | | uint priceSeed,
232 | | uint swapAmount
233 | * | ) public {
234 | * | (address vault, , , ) = _gamma_getVault(seed);
235 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
236 | |
237 | * | SwapOrder(true, true, seed, priceSeed, swapAmount);
238 | * | ExecuteOrder(seed, priceSeed, false);
239 | |
240 | * | DecreasePosition(seed, priceSeed, true);
241 | * | ExecuteOrder(seed, priceSeed, false);
242 | * | NextActionPerps(seed, priceSeed);
243 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
244 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
245 | * | } else if (isNextFinalize(vault)) {
246 | | NextActionPerps(seed, priceSeed);
247 | | }
248 | * | if (
249 | * | initialFlow == PerpetualVault.FLOW.NONE &&
250 | | !PerpetualVaultLens(vault).cancellationTriggered()
251 | | ) {
252 | | gammaGeneralPostconditions(vault, priceSeed);
253 | | }
254 | | }
255 | |
256 | * | function fuzz_GammaRunNextActionWithdraw(
257 | | uint8 seed,
258 | | uint8 userSeed,
259 | | uint priceSeed
260 | * | ) public {
261 | * | (address vault, , , ) = _gamma_getVault(seed);
262 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
263 | |
264 | * | IncreaseOrder(seed, priceSeed, true);
265 | * | ExecuteOrder(seed, priceSeed, false);
266 | |
267 | * | GammaWithdraw(seed, userSeed, priceSeed);
268 | * | ExecuteOrder(seed, priceSeed, false);
269 | |
270 | * | NextActionPerps(seed, priceSeed);
271 | * | ExecuteOrder(seed, priceSeed, false);
272 | * | NextActionPerps(seed, priceSeed);
273 | |
274 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
275 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
276 | | } else if (isNextFinalize(vault)) {
277 | | NextActionPerps(seed, priceSeed);
278 | | }
279 | * | if (
280 | * | initialFlow == PerpetualVault.FLOW.NONE &&
281 | * | !PerpetualVaultLens(vault).cancellationTriggered()
282 | | ) {
283 | | gammaGeneralPostconditions(vault, priceSeed);
284 | | }
285 | | }
286 | |
287 | *r | function fuzz_GammaDepositTwiceRunNextActionWithdraw(
288 | | uint8 seed,
289 | | uint8 userSeed,
290 | | uint priceSeed
291 | * | ) public {
292 | * | (address vault, , , ) = _gamma_getVault(seed);
293 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
294 | |
295 | * | address user = _getRandomUser(userSeed);
296 | |
297 | * | GammaDeposit(seed, userSeed, priceSeed);
298 | |
299 | * | _invariant_GAMMA_12(vault, user);
300 | |
301 | * | IncreaseOrder(seed, priceSeed, true);
302 | * | ExecuteOrder(seed, priceSeed, false);
303 | |
304 | * | GammaWithdraw(seed, userSeed, priceSeed);
305 | * | ExecuteOrder(seed, priceSeed, false);
306 | |
307 | * | NextActionPerps(seed, priceSeed);
308 | * | ExecuteOrder(seed, priceSeed, false);
309 | * | NextActionPerps(seed, priceSeed);
310 | |
311 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
312 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
313 | * | } else if (isNextFinalize(vault)) {
314 | | NextActionPerps(seed, priceSeed);
315 | * | } else if (isNextFinalize(vault)) {}
316 | * | if (
317 | * | initialFlow == PerpetualVault.FLOW.NONE &&
318 | * | !PerpetualVaultLens(vault).cancellationTriggered()
319 | | ) {
320 | * | gammaGeneralPostconditions(vault, priceSeed);
321 | | }
322 | | }
323 | |
324 | *r | function fuzz_GammaRunNextActionSettle(
325 | | uint8 seed,
326 | | uint8 userSeed,
327 | | uint priceSeed
328 | | ) public {
329 | * | (address vault, , , ) = _gamma_getVault(seed);
330 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
331 | |
332 | * | IncreaseOrder(seed, priceSeed, true);
333 | * | ExecuteOrder(seed, priceSeed, false);
334 | |
335 | * | GammaWithdraw(seed, userSeed, priceSeed);
336 | * | ExecuteOrder(seed, priceSeed, false);
337 | |
338 | * | NextActionPerps(seed, priceSeed);
339 | * | ExecuteOrder(seed, priceSeed, false);
340 | |
341 | * | NextActionPerps(seed, priceSeed);
342 | * | ExecuteOrder(seed, priceSeed, false);
343 | | NextActionPerps(seed, priceSeed);
344 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
345 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
346 | | } else if (isNextFinalize(vault)) {
347 | | NextActionPerps(seed, priceSeed);
348 | | }
349 | | if (
350 | | initialFlow == PerpetualVault.FLOW.NONE &&
351 | | !PerpetualVaultLens(vault).cancellationTriggered()
352 | | ) {
353 | | gammaGeneralPostconditions(vault, priceSeed);
354 | | }
355 | | }
356 | |
357 | *r | function fuzz_AfterOrderExecution_DepositMarketIncrease(
358 | | uint8 seed,
359 | | uint8 userSeed,
360 | | uint priceSeed
361 | * | ) public {
362 | * | (address vault, , , ) = _gamma_getVault(seed);
363 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
364 | |
365 | * | ExecuteOrder(seed, priceSeed, false);
366 | * | NextActionPerps(seed, priceSeed);
367 | * | ExecuteOrder(seed, priceSeed, false);
368 | * | NextActionPerps(seed, priceSeed); //this will execute finalize
369 | |
370 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
371 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
372 | * | } else if (isNextFinalize(vault)) {
373 | | NextActionPerps(seed, priceSeed);
374 | | }
375 | * | if (
376 | * | initialFlow == PerpetualVault.FLOW.NONE &&
377 | | !PerpetualVaultLens(vault).cancellationTriggered()
378 | | ) {
379 | | gammaGeneralPostconditions(vault, priceSeed);
380 | | }
381 | | }
382 | |
383 | *r | function fuzz_AfterOrderExecution_WithdrawMarketDecrease(
384 | | uint8 seed,
385 | | uint8 userSeed,
386 | | uint priceSeed
387 | * | ) public {
388 | * | (address vault, , , ) = _gamma_getVault(seed);
389 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
390 | |
391 | * | IncreaseOrder(seed, priceSeed, true);
392 | * | ExecuteOrder(seed, priceSeed, false);
393 | |
394 | * | GammaWithdraw(seed, userSeed, priceSeed);
395 | * | ExecuteOrder(seed, priceSeed, false);
396 | * | NextActionPerps(seed, priceSeed);
397 | * | ExecuteOrder(seed, priceSeed, false);
398 | * | NextActionPerps(seed, priceSeed); //this will execute finalize
399 | |
400 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
401 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
402 | * | } else if (isNextFinalize(vault)) {
403 | | NextActionPerps(seed, priceSeed);
404 | | }
405 | * | if (
406 | * | initialFlow == PerpetualVault.FLOW.NONE &&
407 | * | !PerpetualVaultLens(vault).cancellationTriggered()
408 | | ) {
409 | * | gammaGeneralPostconditions(vault, priceSeed);
410 | | }
411 | | }
412 | |
413 | *r | function fuzz_AfterOrderExecution_WithdrawMarketSwap(
414 | | uint8 seed,
415 | | uint8 userSeed,
416 | | uint priceSeed,
417 | | uint swapAmount
418 | | ) public {
419 | * | (address vault, , , ) = _gamma_getVault(seed);
420 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
421 | |
422 | * | SwapOrder(true, true, seed, priceSeed, swapAmount);
423 | * | ExecuteOrder(seed, priceSeed, false);
424 | |
425 | * | GammaWithdraw(seed, userSeed, priceSeed);
426 | |
427 | | NextActionPerps(seed, priceSeed);
428 | | ExecuteOrder(seed, priceSeed, false);
429 | | NextActionPerps(seed, priceSeed); //this will execute finalize
430 | |
431 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
432 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
433 | | } else if (isNextFinalize(vault)) {
434 | | NextActionPerps(seed, priceSeed);
435 | | }
436 | | if (
437 | | initialFlow == PerpetualVault.FLOW.NONE &&
438 | | !PerpetualVaultLens(vault).cancellationTriggered()
439 | | ) {
440 | | gammaGeneralPostconditions(vault, priceSeed);
441 | | }
442 | | }
443 | |
444 | *r | function fuzz_AfterOrderExecution_GmxSwapNonCollateralToIndex(
445 | | uint8 seed,
446 | | uint8 userSeed,
447 | | uint priceSeed,
448 | | uint swapAmount
449 | | ) public {
450 | * | (address vault, , , ) = _gamma_getVault(seed);
451 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
452 | |
453 | * | SwapOrder(true, true, seed, priceSeed, swapAmount);
454 | * | ExecuteOrder(seed, priceSeed, false);
455 | |
456 | * | DecreasePosition(seed, priceSeed, true);
457 | * | ExecuteOrder(seed, priceSeed, false);
458 | * | NextActionPerps(seed, priceSeed);
459 | * | ExecuteOrder(seed, priceSeed, false);
460 | |
461 | * | ExecuteOrder(seed, priceSeed, false);
462 | | NextActionPerps(seed, priceSeed);
463 | | NextActionPerps(seed, priceSeed); //this will execute finalize
464 | |
465 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
466 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
467 | | } else if (isNextFinalize(vault)) {
468 | | NextActionPerps(seed, priceSeed);
469 | | }
470 | | if (
471 | | initialFlow == PerpetualVault.FLOW.NONE &&
472 | | !PerpetualVaultLens(vault).cancellationTriggered()
473 | | ) {
474 | | gammaGeneralPostconditions(vault, priceSeed);
475 | | }
476 | | }
477 | |
478 | *r | function fuzz_AfterOrderExecution_CompoundSwapToCollateral(
479 | | uint8 seed,
480 | | uint8 userSeed,
481 | | uint priceSeed,
482 | | uint swapAmount
483 | | ) public {
484 | * | (address vault, , , ) = _gamma_getVault(seed);
485 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
486 | |
487 | * | SwapOrder(true, true, seed, priceSeed, swapAmount);
488 | * | ExecuteOrder(seed, priceSeed, false);
489 | |
490 | * | vm.warp(block.timestamp + 7 days); //collect fees
491 | |
492 | * | NextActionPerps(seed, priceSeed);
493 | * | ExecuteOrder(seed, priceSeed, false);
494 | * | NextActionPerps(seed, priceSeed);
495 | * | ExecuteOrder(seed, priceSeed, false);
496 | * | NextActionPerps(seed, priceSeed);
497 | * | NextActionPerps(seed, priceSeed);
498 | |
499 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
500 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
501 | | } else if (isNextFinalize(vault)) {
502 | | NextActionPerps(seed, priceSeed);
503 | | }
504 | | if (
505 | | initialFlow == PerpetualVault.FLOW.NONE &&
506 | | !PerpetualVaultLens(vault).cancellationTriggered()
507 | | ) {
508 | | gammaGeneralPostconditions(vault, priceSeed);
509 | | }
510 | | }
511 | |
512 | *r | function fuzz_Coverage01_SwitchPositionType(
513 | | uint8 seed,
514 | | uint8 userSeed,
515 | | uint priceSeed
516 | * | ) public {
517 | * | (address vault, , , ) = _gamma_getVault(seed);
518 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
519 | |
520 | * | IncreaseOrder(seed, priceSeed, true); // Open long
521 | * | ExecuteOrder(seed, priceSeed, false);
522 | |
523 | * | bool isLong = false; //short
524 | * | IncreaseOrder(seed, priceSeed, isLong);
525 | * | ExecuteOrder(seed, priceSeed, false);
526 | |
527 | * | NextActionPerps(seed, priceSeed);
528 | * | ExecuteOrder(seed, priceSeed, false);
529 | * | NextActionPerps(seed, priceSeed);
530 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
531 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
532 | * | } else if (isNextFinalize(vault)) {
533 | | NextActionPerps(seed, priceSeed);
534 | | }
535 | * | if (
536 | * | initialFlow == PerpetualVault.FLOW.NONE &&
537 | * | !PerpetualVaultLens(vault).cancellationTriggered()
538 | | ) {
539 | * | gammaGeneralPostconditions(vault, priceSeed);
540 | | }
541 | | }
542 | |
543 | *r | function fuzz_withdrawAndCheckFees(
544 | | uint8 vaultSeed,
545 | | uint8 userSeed,
546 | | uint priceSeed,
547 | | bool isLong
548 | * | ) public {
549 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
550 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
551 | *r | require(
552 | * | PerpetualVault(vault).curPositionKey() != bytes32(0),
553 | | "Position should be opened"
554 | | );
555 | |
556 | * | _positionBefore();
557 | * | if (states[0].vaultInfos[vault].totalFees > 0) {
558 | * | DecreasePosition(vaultSeed, priceSeed, isLong);
559 | |
560 | * | ExecuteOrder(vaultSeed, priceSeed, true); //isAtomic
561 | * | NextActionPerps(vaultSeed, priceSeed);
562 | |
563 | * | _gammaBefore();
564 | | (
565 | | ,
566 | * | uint initialDepositAmount,
567 | * | uint depositTimestamp
568 | * | ) = GammaWithdraw(vaultSeed, userSeed, priceSeed);
569 | | _positionAfter();
570 | | require(
571 | | states[1].vaultInfos[vault].totalFees == 0,
572 | | "Position wasn't closed"
573 | | );
574 | | if (
575 | | initialFlow == PerpetualVault.FLOW.NONE &&
576 | | !PerpetualVaultLens(vault).cancellationTriggered()
577 | | ) {
578 | | gammaGeneralPostconditions(vault, priceSeed);
579 | | }
580 | | _invariant_GAMMA_01(userSeed, vaultSeed, initialDepositAmount);
581 | | _invariant_GAMMA_07(vault, depositTimestamp);
582 | | }
583 | | }
584 | |
585 | *r | function fuzz_GammaNextActionCompound(
586 | | uint8 vaultSeed,
587 | | uint8 userSeed,
588 | | uint priceSeed
589 | * | ) public {
590 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
591 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
592 | * | IncreaseExecuteOrder_GuidedBrick_01(userSeed, priceSeed);
593 | * | GammaDeposit(vaultSeed, userSeed, priceSeed);
594 | * | RunNextAction_GuidedBrick_02(vaultSeed, priceSeed);
595 | * | vm.warp(block.timestamp + priceSeed); //collect funding
596 | * | RunNextAction_GuidedBrick_02(vaultSeed, priceSeed);
597 | | }
598 | |
599 | *r | function fuzz_DonateAndCheckExecution(
600 | | uint8 vaultSeed,
601 | | uint8 userSeed,
602 | | uint priceSeed
603 | * | ) public {
604 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
605 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
606 | * | address index = PerpetualVault(vault).indexToken();
607 | |
608 | * | (PerpetualVault.NextActionSelector currentAction, ) = PerpetualVault(
609 | * | vault
610 | | ).nextAction();
611 | |
612 | * | IncreaseOrder(userSeed, priceSeed, true);
613 | |
614 | * | (currentAction, ) = PerpetualVault(vault).nextAction();
615 | * | address nakamoto = _getRandomUser(userSeed + 1); //other user - nakamoto the wealthy
616 | |
617 | * | _mintAndSendTokensTo(
618 | * | nakamoto,
619 | * | address(orderVault),
620 | * | fl.clamp(priceSeed, 0, WETH.balanceOf(nakamoto)), //long token
621 | * | fl.clamp(priceSeed, 0, USDC.balanceOf(nakamoto)), //short token
622 | * | address(index),
623 | * | address(USDC),
624 | * | 0,
625 | * | false
626 | | );
627 | * | ExecuteOrder(userSeed, priceSeed, false);
628 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
629 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
630 | * | } else if (isNextFinalize(vault)) {
631 | * | NextActionPerps(vaultSeed, priceSeed);
632 | | }
633 | |
634 | * | if (
635 | * | initialFlow == PerpetualVault.FLOW.NONE &&
636 | * | !PerpetualVaultLens(vault).cancellationTriggered()
637 | | ) {
638 | * | gammaGeneralPostconditions(vault, priceSeed);
639 | | }
640 | | }
641 | |
642 | *r | function fuzz_openAndLiquidatePosition(
643 | | uint8 vaultSeed,
644 | | uint8 userSeed,
645 | | uint priceSeed
646 | * | ) public {
647 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
648 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
649 | |
650 | * | GammaDeposit(vaultSeed, userSeed, priceSeed);
651 | |
652 | * | IncreaseOrder(vaultSeed, priceSeed, true); // Open long
653 | * | ExecuteOrder(vaultSeed, priceSeed, false);
654 | |
655 | * | LiquidateVault(vaultSeed);
656 | |
657 | * | (bool success, , ) = GammaWithdraw(vaultSeed, userSeed, priceSeed);
658 | * | fl.t(success, "GAMMA-15: WIthdraw failed afted liquidation");
659 | |
660 | * | ExecuteOrder(vaultSeed, priceSeed, false);
661 | |
662 | * | NextActionPerps(vaultSeed, priceSeed);
663 | * | ExecuteOrder(vaultSeed, priceSeed, false); //retry
664 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
665 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
666 | * | } else if (isNextFinalize(vault)) {
667 | | NextActionPerps(vaultSeed, priceSeed);
668 | | }
669 | * | if (
670 | * | initialFlow == PerpetualVault.FLOW.NONE &&
671 | * | !PerpetualVaultLens(vault).cancellationTriggered()
672 | | ) {
673 | | gammaGeneralPostconditions(vault, priceSeed);
674 | | }
675 | | }
676 | |
677 | * | function fuzz_openAndADLVault_PriceGuided(
678 | | uint8 vaultSeed,
679 | | uint8 userSeed,
680 | | uint priceSeed
681 | * | ) public {
682 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
683 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
684 | |
685 | * | uint priceSeed = 1000e4; //from 1k
686 | |
687 | * | GammaDepositAmount(vaultSeed, userSeed, priceSeed, 83000e6); //to 250k x3 lev
688 | |
689 | * | IncreaseOrder(vaultSeed, priceSeed, true);
690 | * | ExecuteOrder(vaultSeed, priceSeed, false);
691 | |
692 | * | ExecuteADLonVault(vaultSeed, 999999e4);
693 | |
694 | * | (bool success, , ) = GammaWithdraw(vaultSeed, userSeed, priceSeed);
695 | * | fl.t(success, "GAMMA-16: WIthdraw failed afted ADL");
696 | |
697 | * | ExecuteOrder(vaultSeed, priceSeed, false);
698 | |
699 | * | NextActionPerps(vaultSeed, priceSeed);
700 | * | ExecuteOrder(vaultSeed, priceSeed, false);
701 | * | NextActionPerps(vaultSeed, priceSeed);
702 | * | gammaGeneralPostconditions(vault, priceSeed);
703 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
704 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
705 | * | } else if (isNextFinalize(vault)) {
706 | | NextActionPerps(vaultSeed, priceSeed);
707 | | }
708 | * | if (
709 | * | initialFlow == PerpetualVault.FLOW.NONE &&
710 | * | !PerpetualVaultLens(vault).cancellationTriggered()
711 | | ) {
712 | * | gammaGeneralPostconditions(vault, priceSeed);
713 | | }
714 | | }
715 | |
716 | *r | function fuzz_openAndADLVault_Free(
717 | | uint8 vaultSeed,
718 | | uint8 userSeed,
719 | | uint priceSeed
720 | * | ) public {
721 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
722 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
723 | |
724 | * | GammaDepositAmount(
725 | * | vaultSeed,
726 | * | userSeed,
727 | * | priceSeed,
728 | * | priceSeed / vaultSeed
729 | | );
730 | |
731 | * | IncreaseOrder(vaultSeed, priceSeed, true);
732 | * | ExecuteOrder(vaultSeed, priceSeed, false);
733 | |
734 | * | ExecuteADLonVault(vaultSeed, priceSeed);
735 | |
736 | * | GammaWithdraw(vaultSeed, userSeed, priceSeed);
737 | * | ExecuteOrder(vaultSeed, priceSeed, false);
738 | |
739 | * | NextActionPerps(vaultSeed, priceSeed);
740 | * | ExecuteOrder(vaultSeed, priceSeed, false);
741 | * | NextActionPerps(vaultSeed, priceSeed);
742 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
743 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
744 | * | } else if (isNextFinalize(vault)) {
745 | | NextActionPerps(vaultSeed, priceSeed);
746 | | }
747 | * | if (
748 | * | initialFlow == PerpetualVault.FLOW.NONE &&
749 | * | !PerpetualVaultLens(vault).cancellationTriggered()
750 | | ) {
751 | * | gammaGeneralPostconditions(vault, priceSeed);
752 | | }
753 | | }
754 | |
755 | | /*
756 | | *
757 | | * GAMMA REMEDIATIONS COVERAGE GUIDANCE
758 | | *
759 | | */
760 | |
761 | *r | function fuzz_GammaDepositOpenCloseDonateWETH_Finalize(
762 | | uint8 vaultSeed,
763 | | uint8 userSeed,
764 | | uint priceSeed
765 | * | ) public {
766 | * | (address vault, , , ) = _gamma_getVault(vaultSeed);
767 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
768 | * | address index = PerpetualVault(vault).indexToken();
769 | |
770 | * | IncreaseOrder(vaultSeed, priceSeed, true); //isLong
771 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
772 | |
773 | * | DecreasePosition(
774 | * | vaultSeed,
775 | * | priceSeed / fl.clamp(userSeed, 1, 10),
776 | * | true
777 | | );
778 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
779 | |
780 | * | _mintAndSendTokensTo(
781 | * | _getRandomUser(1),
782 | * | address(vault),
783 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary
784 | * | 0,
785 | * | address(index),
786 | * | address(0),
787 | * | 0,
788 | * | false
789 | | );
790 | |
791 | * | NextActionPerps(vaultSeed, priceSeed);
792 | |
793 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
794 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic
795 | * | } else if (isNextFinalize(vault)) {
796 | | NextActionPerps(vaultSeed, priceSeed);
797 | | }
798 | * | if (
799 | * | initialFlow == PerpetualVault.FLOW.NONE &&
800 | * | !PerpetualVaultLens(vault).cancellationTriggered()
801 | | ) {
802 | * | gammaGeneralPostconditions(vault, priceSeed);
803 | | }
804 | | }
805 | |
806 | *r | function fuzz_GammaDepositWithOpenPositionDonateWETH(
807 | | uint8 seed,
808 | | uint8 userSeed,
809 | | uint priceSeed
810 | * | ) public {
811 | * | (address vault, , , ) = _gamma_getVault(seed);
812 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
813 | * | address index = PerpetualVault(vault).indexToken();
814 | |
815 | * | GammaDeposit(seed, userSeed, priceSeed);
816 | |
817 | * | _mintAndSendTokensTo(
818 | * | _getRandomUser(1),
819 | * | address(vault),
820 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary,
821 | * | 0,
822 | * | address(index),
823 | * | address(0),
824 | * | 0,
825 | * | false
826 | | );
827 | |
828 | * | IncreaseOrder(seed, priceSeed, false);
829 | |
830 | * | ExecuteOrder(seed, priceSeed, false);
831 | |
832 | * | GammaDeposit(seed, userSeed, priceSeed);
833 | |
834 | * | NextActionPerps(seed, priceSeed);
835 | |
836 | * | ExecuteOrder(seed, priceSeed, false);
837 | |
838 | * | NextActionPerps(seed, priceSeed);
839 | | // NextActionPerps(seed, priceSeed);
840 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
841 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
842 | * | } else if (isNextFinalize(vault)) {
843 | | NextActionPerps(seed, priceSeed);
844 | | }
845 | |
846 | * | if (
847 | * | initialFlow == PerpetualVault.FLOW.NONE &&
848 | * | !PerpetualVaultLens(vault).cancellationTriggered()
849 | | ) {
850 | * | gammaGeneralPostconditions(vault, priceSeed);
851 | | }
852 | | }
853 | |
854 | *r | function fuzz_SwitchPositionType_Donate(
855 | | uint8 seed,
856 | | uint8 userSeed,
857 | | uint priceSeed
858 | * | ) public {
859 | * | (address vault, , , ) = _gamma_getVault(seed);
860 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
861 | * | address index = PerpetualVault(vault).indexToken();
862 | |
863 | * | GammaDeposit(seed, userSeed, priceSeed);
864 | * | _mintAndSendTokensTo(
865 | * | _getRandomUser(1),
866 | * | address(vault),
867 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary,
868 | * | 0,
869 | * | address(index),
870 | * | address(0),
871 | * | 0,
872 | * | false
873 | | );
874 | * | IncreaseOrder(seed, priceSeed, true); // Open long
875 | |
876 | * | ExecuteOrder(seed, priceSeed, false);
877 | |
878 | * | bool isLong = false;
879 | * | IncreaseOrder(seed, priceSeed, isLong);
880 | |
881 | * | ExecuteOrder(seed, priceSeed, false);
882 | |
883 | * | _mintAndSendTokensTo(
884 | * | _getRandomUser(1),
885 | * | address(vault),
886 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary,
887 | * | 0,
888 | * | address(index),
889 | * | address(0),
890 | * | 0,
891 | * | false
892 | | );
893 | |
894 | * | NextActionPerps(seed, priceSeed);
895 | * | ExecuteOrder(seed, priceSeed, false);
896 | |
897 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
898 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
899 | * | } else if (isNextFinalize(vault)) {
900 | | NextActionPerps(seed, priceSeed);
901 | | }
902 | * | if (
903 | * | initialFlow == PerpetualVault.FLOW.NONE &&
904 | * | !PerpetualVaultLens(vault).cancellationTriggered()
905 | | ) {
906 | * | gammaGeneralPostconditions(vault, priceSeed);
907 | | }
908 | | }
909 | |
910 | *r | function fuzz_GammaCloseOneLeveragePosition_Remed(
911 | | uint8 seed,
912 | | uint8 userSeed,
913 | | uint priceSeed
914 | * | ) public {
915 | * | (address vault, , , ) = _gamma_getVault(seed);
916 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
917 | |
918 | * | GammaDeposit(seed, userSeed, priceSeed);
919 | |
920 | * | SwapOrder(
921 | * | true,
922 | * | true,
923 | * | seed,
924 | * | priceSeed,
925 | * | fl.clamp(priceSeed, 100e6, 10000e6)
926 | | ); //arbitrary
927 | |
928 | * | ExecuteOrder(seed, priceSeed, false);
929 | |
930 | * | DecreasePosition(seed, priceSeed, true);
931 | |
932 | * | ExecuteOrder(seed, priceSeed, false);
933 | |
934 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
935 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
936 | * | } else if (isNextFinalize(vault)) {
937 | | NextActionPerps(seed, priceSeed);
938 | | }
939 | * | if (
940 | * | initialFlow == PerpetualVault.FLOW.NONE &&
941 | * | !PerpetualVaultLens(vault).cancellationTriggered()
942 | | ) {
943 | * | gammaGeneralPostconditions(vault, priceSeed);
944 | | }
945 | | }
946 | |
947 | *r | function fuzz_GammaCompoundPositionDonateUSDC(
948 | | uint8 seed,
949 | | uint8 userSeed,
950 | | uint priceSeed
951 | * | ) public {
952 | * | (address vault, , , ) = _gamma_getVault(seed);
953 | * | IncreaseOrder(seed, priceSeed, seed % 2 == 0 ? true : false); //longs/shorts
954 | * | ExecuteOrder(seed, priceSeed, false);
955 | |
956 | * | _mintAndSendTokensTo(
957 | * | _getRandomUser(1), //any
958 | * | address(vault),
959 | * | 0,
960 | * | fl.clamp(priceSeed, 100e6, 10000e9), //arbitrary,
961 | * | address(0),
962 | * | address(USDC),
963 | * | 0,
964 | * | false
965 | | );
966 | |
967 | * | NextActionPerps(seed, priceSeed);
968 | * | ExecuteOrder(seed, priceSeed, false);
969 | * | NextActionPerps(seed, priceSeed);
970 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
971 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic
972 | * | } else if (isNextFinalize(vault)) {
973 | | NextActionPerps(seed, priceSeed);
974 | | }
975 | | }
976 | |
977 | *r | function fuzz_GammaAfterOrderExecutionDeposit(
978 | | uint8 seed,
979 | | uint8 userSeed,
980 | | uint priceSeed
981 | * | ) public {
982 | * | (address vault, , , ) = _gamma_getVault(seed);
983 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
984 | |
985 | * | IncreaseOrder(seed, priceSeed, true); // Open long
986 | * | ExecuteOrder(seed, priceSeed, false);
987 | * | GammaDepositAmount(
988 | * | seed,
989 | * | userSeed,
990 | * | priceSeed,
991 | * | fl.clamp(priceSeed, 100e6, 10000e9)
992 | | ); //arbitrary
993 | * | NextActionPerps(seed, priceSeed);
994 | * | ExecuteOrder(seed, priceSeed, false);
995 | |
996 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
997 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
998 | * | } else if (isNextFinalize(vault)) {
999 | * | NextActionPerps(seed, priceSeed);
1000 | | }
1001 | * | if (
1002 | * | initialFlow == PerpetualVault.FLOW.NONE &&
1003 | * | !PerpetualVaultLens(vault).cancellationTriggered()
1004 | | ) {
1005 | * | gammaGeneralPostconditions(vault, priceSeed);
1006 | | }
1007 | | }
1008 | |
1009 | *r | function fuzz_GammaAfterOrderExecutionWithdraw(
1010 | | uint8 seed,
1011 | | uint8 userSeed,
1012 | | uint priceSeed
1013 | * | ) public {
1014 | * | (address vault, , , ) = _gamma_getVault(seed);
1015 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow();
1016 | |
1017 | * | GammaDeposit(seed, userSeed, priceSeed);
1018 | * | IncreaseOrder(seed, priceSeed, true); // Open long
1019 | * | ExecuteOrder(seed, priceSeed, false);
1020 | * | GammaWithdraw(seed, userSeed, 50000e4);
1021 | * | NextActionPerps(seed, priceSeed);
1022 | * | ExecuteOrder(seed, priceSeed, false);
1023 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) {
1024 | | ExecuteOrder(seed, priceSeed, false); //isAtomic
1025 | * | } else if (isNextFinalize(vault)) {
1026 | | NextActionPerps(seed, priceSeed);
1027 | | }
1028 | * | if (
1029 | * | initialFlow == PerpetualVault.FLOW.NONE &&
1030 | * | !PerpetualVaultLens(vault).cancellationTriggered()
1031 | | ) {
1032 | * | gammaGeneralPostconditions(vault, priceSeed);
1033 | | }
1034 | | }
1035 | |
1036 | *r | function IncreaseExecuteOrder_GuidedBrick_01(
1037 | | //long
1038 | | uint8 userSeed,
1039 | | uint priceSeed
1040 | | ) public {
1041 | * | IncreaseOrder(userSeed, priceSeed, true); // Open long
1042 | * | ExecuteOrder(userSeed, priceSeed, false);
1043 | | }
1044 | |
1045 | *r | function RunNextAction_GuidedBrick_02(
1046 | | uint8 vaultSeed,
1047 | | uint priceSeed
1048 | | ) public {
1049 | * | NextActionPerps(vaultSeed, priceSeed);
1050 | * | ExecuteOrder(vaultSeed, priceSeed, false);
1051 | | }
1052 | | }
1053 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/LiquidationSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./PropertiesSetup.sol";
6 | | import "../../contracts/market/MarketUtils.sol";
7 | |
8 | | contract LiquidationSetup is PropertiesSetup {
9 | * | function LiquidateVault(uint8 userIndex) public {
10 | * | (, , , address user) = _gamma_getVault(userIndex); //gmxUtils is a holder of position
11 | |
12 | * | uint256 positionCountBefore = PositionStoreUtils.getPositionCount(
13 | * | dataStore
14 | | );
15 | |
16 | * | Position.Props[] memory positions = reader.getAccountPositions(
17 | * | dataStore,
18 | * | user,
19 | * | 0,
20 | * | 10
21 | | ); //@coverage:limiter
22 | * | Position.Props memory positionToLiquidate = positions[0];
23 | |
24 | * | bytes32 positionKey = Position.getPositionKey(
25 | * | user,
26 | * | positionToLiquidate.addresses.market,
27 | * | positionToLiquidate.addresses.collateralToken,
28 | * | positionToLiquidate.flags.isLong
29 | | );
30 | |
31 | * | Market.Props memory marketProps = MarketStoreUtils.get(
32 | * | dataStore,
33 | * | positionToLiquidate.addresses.market
34 | | );
35 | |
36 | * | TokenPrices memory tokenPrices = _setTokenPrices(
37 | * | 1 //priceseed for the minimal price
38 | | );
39 | |
40 | * | (
41 | * | bool isLiquidatable /*string memory */,
42 | | ,
43 | * | PositionUtils.IsPositionLiquidatableInfo
44 | | memory isPositionLiquidatableInfo
45 | * | ) = PositionUtils.isPositionLiquidatable(
46 | * | dataStore,
47 | * | referralStorage,
48 | * | positionToLiquidate, //Position.Props memory position,
49 | * | marketProps, //Market.Props memory market,
50 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), //MarketUtils.MarketPrices memory prices
51 | * | true // bool shouldValidateMinCollateralUsd
52 | | );
53 | |
54 | *r | require(isLiquidatable, "Position is not liquidatable");
55 | |
56 | * | _liquidate(
57 | * | user,
58 | * | positionToLiquidate.addresses.market,
59 | * | positionToLiquidate.addresses.collateralToken,
60 | * | positionToLiquidate.flags.isLong,
61 | * | tokenPrices
62 | | );
63 | |
64 | * | uint256 positionCountAfter = PositionStoreUtils.getPositionCount(
65 | * | dataStore
66 | | );
67 | |
68 | * | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils
69 | * | .getAutoCancelOrderKeys(dataStore, positionKey);
70 | |
71 | * | invariantPositionCountShouldDecrease(
72 | * | positionCountAfter,
73 | * | positionCountBefore
74 | | );
75 | * | invariantPositionCountDecreasesByOne(
76 | * | positionCountAfter,
77 | * | positionCountBefore
78 | | );
79 | * | invariantAutoCancelListShouldBeEmptyAfterLiquidation(
80 | * | autoCancelOrderKeys.length
81 | | );
82 | |
83 | * | _checkPositionLiquitatableCoverage(
84 | * | user,
85 | * | positionToLiquidate.addresses.market,
86 | * | positionToLiquidate.addresses.collateralToken,
87 | * | positionToLiquidate.flags.isLong,
88 | * | isPositionLiquidatableInfo
89 | | );
90 | | }
91 | |
92 | * | function Liquidate(uint8 userIndex) public {
93 | * | address user = _getRandomUser(userIndex);
94 | |
95 | * | uint256 positionCountBefore = PositionStoreUtils.getPositionCount(
96 | * | dataStore
97 | | );
98 | |
99 | * | Position.Props[] memory positions = reader.getAccountPositions(
100 | * | dataStore,
101 | * | user,
102 | * | 0,
103 | * | 10
104 | | ); //@coverage:limiter
105 | * | Position.Props memory positionToLiquidate = positions[0];
106 | |
107 | * | bytes32 positionKey = Position.getPositionKey(
108 | * | user,
109 | * | positionToLiquidate.addresses.market,
110 | * | positionToLiquidate.addresses.collateralToken,
111 | * | positionToLiquidate.flags.isLong
112 | | );
113 | |
114 | * | Market.Props memory marketProps = MarketStoreUtils.get(
115 | * | dataStore,
116 | * | positionToLiquidate.addresses.market
117 | | );
118 | |
119 | * | TokenPrices memory tokenPrices = _setTokenPrices(
120 | * | 1 //priceseed for the minimal price
121 | | );
122 | |
123 | * | (
124 | * | bool isLiquidatable /*string memory */,
125 | | ,
126 | * | PositionUtils.IsPositionLiquidatableInfo
127 | | memory isPositionLiquidatableInfo
128 | * | ) = PositionUtils.isPositionLiquidatable(
129 | * | dataStore,
130 | * | referralStorage,
131 | * | positionToLiquidate, //Position.Props memory position,
132 | * | marketProps, //Market.Props memory market,
133 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), //MarketUtils.MarketPrices memory prices
134 | * | true // bool shouldValidateMinCollateralUsd
135 | | );
136 | |
137 | *r | require(isLiquidatable, "Position is not liquidatable");
138 | |
139 | | _liquidate(
140 | | user,
141 | | positionToLiquidate.addresses.market,
142 | | positionToLiquidate.addresses.collateralToken,
143 | | positionToLiquidate.flags.isLong,
144 | | tokenPrices
145 | | );
146 | |
147 | | uint256 positionCountAfter = PositionStoreUtils.getPositionCount(
148 | | dataStore
149 | | );
150 | |
151 | | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils
152 | | .getAutoCancelOrderKeys(dataStore, positionKey);
153 | |
154 | | invariantPositionCountShouldDecrease(
155 | | positionCountAfter,
156 | | positionCountBefore
157 | | );
158 | | invariantPositionCountDecreasesByOne(
159 | | positionCountAfter,
160 | | positionCountBefore
161 | | );
162 | | invariantAutoCancelListShouldBeEmptyAfterLiquidation(
163 | | autoCancelOrderKeys.length
164 | | );
165 | |
166 | | _checkPositionLiquitatableCoverage(
167 | | user,
168 | | positionToLiquidate.addresses.market,
169 | | positionToLiquidate.addresses.collateralToken,
170 | | positionToLiquidate.flags.isLong,
171 | | isPositionLiquidatableInfo
172 | | );
173 | | }
174 | |
175 | * | function _liquidate(
176 | | address account,
177 | | address market,
178 | | address collateralToken,
179 | | bool isLong,
180 | | TokenPrices memory tokenPrices
181 | * | ) internal {
182 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
183 | * | tokenPrices.tokens,
184 | * | tokenPrices.maxPrices,
185 | * | tokenPrices.minPrices
186 | | );
187 | |
188 | * | vm.prank(DEPLOYER);
189 | * | (bool success, bytes memory data) = address(liquidationHandler).call(
190 | * | abi.encodeWithSelector(
191 | * | LiquidationHandler.executeLiquidation.selector,
192 | * | account,
193 | * | market,
194 | * | collateralToken,
195 | * | isLong,
196 | * | oracleParams
197 | | )
198 | | );
199 | * | if (!success) {
200 | | invariantDoesNotSilentRevert(data);
201 | | }
202 | | }
203 | | }
204 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/MintSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./BaseSetup.sol";
5 | |
6 | | contract MintSetup is BaseSetup {
7 | * | function _mintAndSendTokensTo(
8 | | address user,
9 | | address to,
10 | | uint256 longTokenAmount,
11 | | uint256 shortTokenAmount,
12 | | address longTokenAddress,
13 | | address shortTokenAddress,
14 | | uint executionFee,
15 | | bool isWETH
16 | | ) internal {
17 | * | if (longTokenAddress != address(0)) {
18 | * | _handleTokenMintAndTransfer(
19 | * | user,
20 | * | to,
21 | * | longTokenAmount,
22 | * | longTokenAddress,
23 | * | executionFee,
24 | * | isWETH
25 | | );
26 | | }
27 | |
28 | * | if (shortTokenAddress != address(0)) {
29 | * | _handleTokenMintAndTransfer(
30 | * | user,
31 | * | to,
32 | * | shortTokenAmount,
33 | * | shortTokenAddress,
34 | * | executionFee,
35 | * | isWETH
36 | | );
37 | | }
38 | |
39 | * | vm.prank(user);
40 | * | WETH.deposit{value: executionFee}();
41 | * | vm.prank(user);
42 | * | WETH.transfer(to, executionFee);
43 | | }
44 | |
45 | * | function _handleTokenMintAndTransfer(
46 | | address user,
47 | | address to,
48 | | uint256 amount,
49 | | address tokenAddress,
50 | | uint executionFee,
51 | | bool isWETH
52 | | ) private {
53 | * | if (isWETH && tokenAddress == address(WETH)) {
54 | | //mint happens in FuzzSetup
55 | * | vm.prank(user);
56 | *r | WETH.transfer(to, amount);
57 | | } else {
58 | * | vm.prank(user);
59 | *r | MintableToken(tokenAddress).transfer(to, amount);
60 | | }
61 | | }
62 | | }
63 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/OracleSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./BaseSetup.sol";
5 | |
6 | | contract OracleSetup is BaseSetup {
7 | | mapping(address => uint256) private minTokenPrices;
8 | | mapping(address => uint256) private maxTokenPrices;
9 | |
10 | * | function SetOraclePrices(
11 | | address[] memory tokens,
12 | | uint256[] memory maxPrices,
13 | | uint256[] memory minPrices
14 | * | ) internal returns (OracleUtils.SetPricesParams memory) {
15 | * | require(
16 | * | tokens.length == minPrices.length && tokens.length == maxPrices.length,
17 | | "Tokens, minPrices, and maxPrices arrays must have the same length"
18 | | );
19 | |
20 | * | for (uint256 i = 0; i < tokens.length; i++) {
21 | * | _setMinPrice(tokens[i], minPrices[i]);
22 | * | _setMaxPrice(tokens[i], maxPrices[i]);
23 | | }
24 | |
25 | * | OracleUtils.SetPricesParams memory oracleParams = _setupOracleParams(tokens);
26 | * | return oracleParams;
27 | | }
28 | |
29 | | function SetOraclePrices(
30 | | address[] memory tokens,
31 | | uint[] memory prices
32 | | ) internal returns (OracleUtils.SetPricesParams memory) {
33 | | require(
34 | | tokens.length == prices.length,
35 | | "Tokens and prices arrays must have the same length"
36 | | );
37 | |
38 | | for (uint256 i = 0; i < tokens.length; i++) {
39 | | _setMinPrice(tokens[i], prices[i]);
40 | | _setMaxPrice(tokens[i], prices[i]);
41 | | }
42 | |
43 | | OracleUtils.SetPricesParams memory oracleParams = _setupOracleParams(tokens);
44 | |
45 | | return oracleParams;
46 | | }
47 | |
48 | * | function _setMinPrice(address token, uint256 price) internal {
49 | * | require(price > 0, "Zero price is not supported");
50 | * | require(
51 | * | token == address(WETH) ||
52 | * | token == address(WBTC) ||
53 | * | token == address(USDC) ||
54 | * | token == address(USDT) ||
55 | * | token == SOL,
56 | | "Unsupported token"
57 | | );
58 | * | minTokenPrices[token] = price;
59 | | }
60 | |
61 | * | function _setMaxPrice(address token, uint256 price) internal {
62 | * | require(
63 | * | token == address(WETH) ||
64 | * | token == address(WBTC) ||
65 | * | token == address(USDC) ||
66 | * | token == address(USDT) ||
67 | * | token == address(SOL),
68 | | "Unsupported token"
69 | | );
70 | * | maxTokenPrices[token] = price;
71 | | }
72 | |
73 | * | function _setupOracleParams(
74 | | address[] memory tokens
75 | * | ) internal returns (OracleUtils.SetPricesParams memory) {
76 | * | uint256[] memory precisions = _getPrecisions(tokens);
77 | * | uint256[] memory minPrices = _getMinPrices(tokens);
78 | * | uint256[] memory maxPrices = _getMaxPrices(tokens);
79 | * | address[] memory providers = _getProviders(tokens);
80 | |
81 | * | _setTokenPrices(tokens, minPrices, maxPrices, precisions, providers);
82 | |
83 | * | OracleUtils.SetPricesParams memory oracleParams = OracleUtils.SetPricesParams({
84 | * | tokens: tokens,
85 | * | providers: providers,
86 | * | data: new bytes[](tokens.length)
87 | | });
88 | |
89 | * | return oracleParams;
90 | | }
91 | |
92 | * | function _setTokenPrices(
93 | | address[] memory tokens,
94 | | uint256[] memory minPrices,
95 | | uint256[] memory maxPrices,
96 | | uint256[] memory precisions,
97 | | address[] memory providers
98 | | ) internal {
99 | * | for (uint256 i = 0; i < tokens.length; i++) {
100 | * | chainlinkMock.setOraclePrice(tokens[i], minPrices[i], maxPrices[i], precisions[i]);
101 | | }
102 | | }
103 | |
104 | * | function _getPrecisions(address[] memory tokens) internal view returns (uint256[] memory) {
105 | * | uint256[] memory precisions = new uint[](tokens.length);
106 | * | for (uint256 i = 0; i < tokens.length; i++) {
107 | * | precisions[i] = _getPrecision(tokens[i]);
108 | | }
109 | * | return precisions;
110 | | }
111 | |
112 | * | function _getMinPrices(address[] memory tokens) internal view returns (uint256[] memory) {
113 | * | uint256[] memory minPrices = new uint[](tokens.length);
114 | * | for (uint256 i = 0; i < tokens.length; i++) {
115 | * | minPrices[i] = _getMinPrice(tokens[i]);
116 | | }
117 | * | return minPrices;
118 | | }
119 | |
120 | * | function _getMaxPrices(address[] memory tokens) internal view returns (uint256[] memory) {
121 | * | uint256[] memory maxPrices = new uint[](tokens.length);
122 | * | for (uint256 i = 0; i < tokens.length; i++) {
123 | * | maxPrices[i] = _getMaxPrice(tokens[i]);
124 | | }
125 | * | return maxPrices;
126 | | }
127 | |
128 | * | function _getProviders(address[] memory tokens) internal view returns (address[] memory) {
129 | * | address[] memory providers = new address[](tokens.length);
130 | * | for (uint256 i = 0; i < tokens.length; i++) {
131 | * | providers[i] = address(chainlinkMock);
132 | | }
133 | * | return providers;
134 | | }
135 | |
136 | * | function _getMinPrice(address token) internal view returns (uint256) {
137 | * | uint256 price = minTokenPrices[token];
138 | |
139 | * | require(price != 0, "Min price not set for token");
140 | * | return price;
141 | | }
142 | |
143 | * | function _getMaxPrice(address token) internal view returns (uint256) {
144 | * | uint256 price = maxTokenPrices[token];
145 | |
146 | * | require(price != 0, "Max price not set for token");
147 | * | return price;
148 | | }
149 | | }
150 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/PropertiesSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./OracleSetup.sol";
5 | | import "./MintSetup.sol";
6 | | import "../properties/Properties.sol";
7 | |
8 | | contract PropertiesSetup is OracleSetup, MintSetup, Properties {}
9 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/depositSetup/DepositSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../../contracts/market/MarketUtils.sol";
6 | | import "../../../contracts/deposit/DepositUtils.sol";
7 | | import "./../PropertiesSetup.sol";
8 | |
9 | | contract DepositSetup is PropertiesSetup {
10 | | DepositCreated[] internal depositCreatedArray;
11 | |
12 | | /**
13 | | //
14 | | // GAMMA deposits
15 | | //
16 | | */
17 | |
18 | *r | function GammaDeposit(uint8 seed, uint8 userSeed, uint priceSeed) public {
19 | | //--GAMMA REVERT DEPOSIT START
20 | | //WITHOUT SETTING PRICES IN GMX ORACLE WE CAN NOT DEPOSIT
21 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
22 | |
23 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
24 | * | tokenPrices.tokens,
25 | * | tokenPrices.maxPrices,
26 | * | tokenPrices.minPrices
27 | | );
28 | * | vm.prank(DEPLOYER);
29 | * | oracle.setPrices(oracleParams);
30 | | //--GAMMA REVERT DEPOSIT END
31 | |
32 | * | (address vault, , , ) = _gamma_getVault(seed);
33 | *r | require(
34 | * | PerpetualVaultLens(vault).checkForCleanStart(),
35 | | "Previous call was not executed"
36 | | );
37 | * | uint256 amount = fl.clamp(
38 | * | priceSeed,
39 | * | PerpetualVault(vault).minDepositAmount(),
40 | * | PerpetualVault(vault).maxDepositAmount()
41 | | );
42 | * | IERC20 collateralToken = PerpetualVault(vault).collateralToken();
43 | * | address user = _getRandomUser(userSeed);
44 | * | uint256 executionFee = PerpetualVault(vault).getExecutionGasLimit(true);
45 | |
46 | * | vm.prank(user);
47 | * | collateralToken.approve(vault, type(uint256).max);
48 | |
49 | | //prank inside:)
50 | * | (bool success, bytes memory returnData) = _gamma_DepositCall(
51 | * | user,
52 | * | vault,
53 | * | amount,
54 | * | executionFee
55 | | );
56 | |
57 | * | if (returnData.length > 0) {
58 | * | fl.log(
59 | | "Gamma deposit return data",
60 | * | abi.decode(returnData, (string))
61 | | );
62 | | }
63 | | //--GAMMA REVERT DEPOSIT START
64 | * | vm.prank(DEPLOYER);
65 | * | oracle.clearAllPrices();
66 | | //--GAMMA REVERT DEPOSIT START
67 | |
68 | * | require(success, "Deposit to Gamma failed");
69 | | }
70 | |
71 | *r | function GammaCancelDeposit(uint8 seed) public {
72 | * | (address vault, , , ) = _gamma_getVault(seed);
73 | |
74 | * | (bool success, bytes memory returnData) = _gamma_CanceDepositCall(
75 | * | vault,
76 | * | gammaKeeper
77 | | );
78 | *r | require(success, "Cancel Deposit failed ");
79 | | }
80 | * | function GammaDepositAmount(
81 | | uint8 seed,
82 | | uint8 userSeed,
83 | | uint priceSeed,
84 | | uint specificAmount
85 | * | ) public {
86 | | //--GAMMA REVERT DEPOSIT START
87 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
88 | |
89 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
90 | * | tokenPrices.tokens,
91 | * | tokenPrices.maxPrices,
92 | * | tokenPrices.minPrices
93 | | );
94 | * | vm.prank(DEPLOYER);
95 | * | oracle.setPrices(oracleParams);
96 | | //--GAMMA REVERT DEPOSIT END
97 | |
98 | * | (address vault, , , ) = _gamma_getVault(seed);
99 | *r | require(
100 | * | PerpetualVaultLens(vault).checkForCleanStart(),
101 | | "Previous call was not executed"
102 | | );
103 | |
104 | * | IERC20 collateralToken = PerpetualVault(vault).collateralToken();
105 | * | address user = _getRandomUser(userSeed);
106 | * | uint256 executionFee = PerpetualVault(vault).getExecutionGasLimit(true);
107 | |
108 | * | vm.prank(user);
109 | * | collateralToken.approve(vault, type(uint256).max);
110 | |
111 | | //prank inside:)
112 | * | (bool success, bytes memory returnData) = _gamma_DepositCall(
113 | * | user,
114 | * | vault,
115 | * | specificAmount,
116 | * | executionFee
117 | | );
118 | |
119 | * | if (returnData.length > 0) {
120 | * | fl.log(
121 | | "Gamma deposit return data",
122 | * | abi.decode(returnData, (string))
123 | | );
124 | | }
125 | | //--GAMMA REVERT DEPOSIT START
126 | * | vm.prank(DEPLOYER);
127 | * | oracle.clearAllPrices();
128 | | //--GAMMA REVERT DEPOSIT START
129 | |
130 | * | require(success, "Deposit to Gamma failed");
131 | | }
132 | |
133 | | /**
134 | | //
135 | | // GMX deposits
136 | | //
137 | | */
138 | |
139 | *r | function CreateDeposit(
140 | | uint8 marketIndex,
141 | | uint8 userIndex,
142 | | uint longAmount,
143 | | uint shortAmount,
144 | | uint priceSeed,
145 | | uint executionFee,
146 | | uint8 swapPathSeed
147 | * | ) public returns (DepositCreated memory depositCreated) {
148 | * | depositCreated = _createDeposit(
149 | * | marketIndex,
150 | * | userIndex,
151 | * | longAmount,
152 | * | shortAmount,
153 | * | priceSeed,
154 | * | SWAPS_ENABLED ? swapPathSeed : 7, //7 is empty swap path
155 | * | executionFee,
156 | * | false
157 | | );
158 | | return depositCreated;
159 | | }
160 | |
161 | * | function _createDeposit(
162 | | uint8 marketIndex,
163 | | uint8 userIndex,
164 | | uint longAmount,
165 | | uint shortAmount,
166 | | uint priceSeed,
167 | | uint8 swapPathSeed,
168 | | uint executionFee,
169 | | bool InitialDeposit
170 | * | ) internal returns (DepositCreated memory depositCreated) {
171 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT;
172 | |
173 | * | if (!SWAPS_ENABLED) {
174 | * | swapPathSeed = 7;
175 | | }
176 | | //avoiding stack too deep
177 | * | depositCreated.longSwapPath = _getSwapPath(swapPathSeed);
178 | * | depositCreated.shortSwapPath = _getSwapPath(
179 | * | SWAPS_ENABLED ? swapPathSeed / 5 : 7
180 | | ); //another path
181 | |
182 | * | address user = _getRandomUser(userIndex);
183 | * | address market = _getMarketAddress(marketIndex);
184 | |
185 | * | Market.Props memory marketProps = MarketStoreUtils.get(
186 | * | dataStore,
187 | * | market
188 | | );
189 | |
190 | * | (longAmount, shortAmount) = _getTokenAmounts(
191 | * | longAmount,
192 | * | shortAmount,
193 | * | marketProps.longToken,
194 | * | marketProps.shortToken,
195 | * | user
196 | | );
197 | |
198 | * | bool isWETH = marketProps.longToken == address(WETH) ||
199 | * | marketProps.shortToken == address(WETH);
200 | |
201 | * | DepositorParams memory depositorParams = _setDepositorParams(
202 | * | user,
203 | * | longAmount,
204 | * | shortAmount,
205 | * | isWETH
206 | | );
207 | |
208 | * | DepositParams memory depositParams = _setDepositParams(
209 | * | user,
210 | * | address(callback),
211 | * | address(0), //uiFeeReceiver
212 | * | depositCreated.longSwapPath,
213 | * | depositCreated.shortSwapPath,
214 | * | 1, //minMarketTokens
215 | * | false, //isWETH, not wrapping
216 | * | InitialDeposit ? 0 : FIXED_EXECUTION_FEE_AMOUNT,
217 | * | 200 * 1000
218 | | );
219 | |
220 | * | depositCreated.depositorParams = depositorParams;
221 | * | depositCreated.depositParams = depositParams;
222 | * | depositCreated.beforeDepositExec.marketTotalSupply = ERC20(
223 | * | marketProps.marketToken
224 | | ).totalSupply();
225 | * | depositCreated.beforeDepositExec.userBalanceMarket = ERC20(
226 | * | marketProps.marketToken
227 | * | ).balanceOf(depositorParams.user);
228 | |
229 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
230 | * | depositCreated.tokenPrices = tokenPrices;
231 | |
232 | * | (
233 | * | depositCreated.key,
234 | * | depositCreated.beforeDepositExec.simulateDepositAmountOut,
235 | * | depositCreated.createDepositParams
236 | * | ) = _createDeposit(
237 | * | depositorParams,
238 | * | depositParams,
239 | * | marketProps,
240 | * | tokenPrices,
241 | * | executionFee
242 | | );
243 | |
244 | * | depositCreatedArray.push(depositCreated);
245 | |
246 | * | _checkCreateDepositCoverage(
247 | * | depositCreated.createDepositParams.market,
248 | * | depositCreated.createDepositParams.initialLongToken,
249 | * | depositCreated.createDepositParams.initialShortToken,
250 | * | depositCreated.tokenPrices,
251 | * | depositCreated.depositorParams.user,
252 | * | depositCreated.depositorParams.longAmount,
253 | * | depositCreated.depositorParams.shortAmount
254 | | );
255 | | }
256 | |
257 | * | function _createDeposit(
258 | | DepositorParams memory depositorParams,
259 | | DepositParams memory depositParams,
260 | | Market.Props memory marketProps,
261 | | TokenPrices memory tokenPrices,
262 | | uint executionFee
263 | | )
264 | | internal
265 | | returns (
266 | * | bytes32 depositKey,
267 | * | uint simulateDepositAmountOut,
268 | * | DepositUtils.CreateDepositParams memory createDepositParams
269 | | )
270 | * | {
271 | * | createDepositParams = _setDepositParams(depositParams, marketProps);
272 | |
273 | * | _mintAndSendTokensTo(
274 | * | depositorParams.user,
275 | * | address(depositVault),
276 | * | depositorParams.longAmount,
277 | * | depositorParams.shortAmount,
278 | * | marketProps.longToken,
279 | * | marketProps.shortToken,
280 | * | executionFee,
281 | * | depositorParams.isWETH
282 | | );
283 | |
284 | * | simulateDepositAmountOut = ReaderDepositUtils.getDepositAmountOut(
285 | * | dataStore,
286 | * | marketProps,
287 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
288 | * | depositorParams.longAmount,
289 | * | depositorParams.shortAmount,
290 | * | address(0),
291 | * | ISwapPricingUtils.SwapPricingType.TwoStep, // TwoStep, Shift, Atomic
292 | * | false //includeVirtualInventoryImpact
293 | | );
294 | |
295 | * | bytes memory callData_CreateDeposit = abi.encodeWithSelector(
296 | * | exchangeRouter.createDeposit.selector,
297 | * | createDepositParams
298 | | );
299 | * | vm.prank(depositorParams.user);
300 | |
301 | * | (
302 | * | bool success_CreateDeposit,
303 | * | bytes memory returnData_CreateDeposit
304 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(
305 | * | callData_CreateDeposit
306 | | );
307 | |
308 | * | if (!success_CreateDeposit) {
309 | | invariantDoesNotSilentRevert(returnData_CreateDeposit);
310 | | } else {
311 | * | depositKey = abi.decode(returnData_CreateDeposit, (bytes32));
312 | | }
313 | | }
314 | |
315 | *r | function CancelDeposit(
316 | | uint seed,
317 | | bool isAtomicExec
318 | | )
319 | | public
320 | | returns (
321 | * | DepositState memory _before,
322 | * | DepositState memory _after,
323 | * | DepositCreated memory depositToCancel
324 | | )
325 | | {
326 | *r | require(
327 | * | depositCreatedArray.length > 0,
328 | | "No deposits available to cancel"
329 | | );
330 | |
331 | * | uint256 randomIndex = isAtomicExec
332 | * | ? depositCreatedArray.length - 1
333 | * | : clampBetween(seed, 0, depositCreatedArray.length - 1);
334 | |
335 | * | depositToCancel = depositCreatedArray[randomIndex];
336 | |
337 | * | _before = _snapDepositState(
338 | * | depositToCancel.createDepositParams.receiver,
339 | * | depositToCancel.createDepositParams.market
340 | | );
341 | |
342 | * | bytes memory callData_CancelDeposit = abi.encodeWithSelector(
343 | * | exchangeRouter.cancelDeposit.selector,
344 | * | depositToCancel.key
345 | | );
346 | |
347 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
348 | * | vm.prank(depositToCancel.createDepositParams.receiver);
349 | |
350 | * | (
351 | * | bool success_CancelDeposit,
352 | * | bytes memory returnData_CancelDeposit
353 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(
354 | * | callData_CancelDeposit
355 | | );
356 | |
357 | * | if (!success_CancelDeposit) {
358 | * | invariantDoesNotSilentRevert(returnData_CancelDeposit);
359 | | }
360 | |
361 | | _after = _snapDepositState(
362 | | depositToCancel.createDepositParams.receiver,
363 | | depositToCancel.createDepositParams.market
364 | | );
365 | |
366 | | _checkCancelDepositCoverage(
367 | | depositToCancel.createDepositParams.market,
368 | | depositToCancel.createDepositParams.initialLongToken,
369 | | depositToCancel.createDepositParams.initialShortToken,
370 | | depositToCancel.tokenPrices,
371 | | depositToCancel.depositorParams.user,
372 | | depositToCancel.depositorParams.longAmount,
373 | | depositToCancel.depositorParams.shortAmount
374 | | );
375 | | }
376 | |
377 | *r | function ExecuteDeposit(
378 | | uint priceSeed,
379 | | bool isAtomicExec
380 | * | ) public returns (DepositCreated memory, DepositState memory) {
381 | *r | require(
382 | * | depositCreatedArray.length > 0,
383 | | "No deposits available to execute"
384 | | );
385 | |
386 | * | uint256 randomIndex = isAtomicExec
387 | * | ? depositCreatedArray.length - 1
388 | * | : clampBetween(priceSeed, 0, depositCreatedArray.length - 1);
389 | |
390 | * | DepositCreated memory depositToExecute = depositCreatedArray[
391 | * | randomIndex
392 | | ];
393 | |
394 | * | Market.Props memory marketProps = MarketStoreUtils.get(
395 | * | dataStore,
396 | * | depositToExecute.createDepositParams.market
397 | | );
398 | |
399 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
400 | |
401 | | //state before recorded in DepositCreated struct on create deposit step
402 | * | DepositState memory coverageCheck = _snapDepositState(
403 | * | depositToExecute.createDepositParams.receiver,
404 | * | depositToExecute.createDepositParams.market
405 | | );
406 | * | _executeDeposit(depositToExecute, marketProps, tokenPrices);
407 | |
408 | | //state after
409 | * | DepositState memory afterDepositExecution = _snapDepositState(
410 | * | depositToExecute.createDepositParams.receiver,
411 | * | depositToExecute.createDepositParams.market
412 | | );
413 | |
414 | * | depositCreatedArray[randomIndex] = depositCreatedArray[
415 | * | depositCreatedArray.length - 1
416 | | ];
417 | * | depositCreatedArray.pop();
418 | |
419 | * | _checkCoverageAfterDepositExecution(
420 | * | coverageCheck.market,
421 | * | coverageCheck.userBalanceMarket,
422 | * | coverageCheck.marketTotalSupply
423 | | );
424 | |
425 | * | return (depositToExecute, afterDepositExecution);
426 | | }
427 | |
428 | * | function _executeDeposit(
429 | | DepositCreated memory depositCreated,
430 | | Market.Props memory marketProps,
431 | | TokenPrices memory tokenPrices
432 | * | ) internal {
433 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
434 | * | tokenPrices.tokens,
435 | * | tokenPrices.maxPrices,
436 | * | tokenPrices.minPrices
437 | | );
438 | |
439 | * | DepositState memory _before = _snapDepositState(
440 | * | depositCreated.depositorParams.user,
441 | * | marketProps.marketToken
442 | | );
443 | |
444 | * | bytes memory callData_ExecuteDeposit = abi.encodeWithSelector(
445 | * | depositHandler.executeDeposit.selector,
446 | * | depositCreated.key,
447 | * | oracleParams
448 | | );
449 | * | vm.prank(DEPLOYER);
450 | |
451 | * | (
452 | * | bool success_ExecuteDeposit,
453 | * | bytes memory returnData_ExecuteDeposit
454 | * | ) = address(depositHandler).call{gas: 30_000_000}(
455 | * | callData_ExecuteDeposit
456 | | );
457 | |
458 | * | if (!success_ExecuteDeposit) {
459 | * | invariantDoesNotSilentRevert(returnData_ExecuteDeposit);
460 | | }
461 | |
462 | * | DepositState memory _after = _snapDepositState(
463 | * | depositCreated.depositorParams.user,
464 | * | marketProps.marketToken
465 | | );
466 | |
467 | *r | require(
468 | * | _before.userBalanceMarket < _after.userBalanceMarket,
469 | | "Deposit state was not changed"
470 | | );
471 | | }
472 | |
473 | * | function _setDepositorParams(
474 | | address user,
475 | | uint256 longAmount,
476 | | uint256 shortAmount,
477 | | bool isWETH
478 | * | ) internal returns (DepositorParams memory) {
479 | * | DepositorParams memory depositorParams = DepositorParams({
480 | * | user: user,
481 | * | longAmount: longAmount,
482 | * | shortAmount: shortAmount,
483 | * | isWETH: isWETH
484 | | });
485 | |
486 | * | return depositorParams;
487 | | }
488 | |
489 | * | function _setDepositParams(
490 | | address receiver,
491 | | address callbackContract,
492 | | address uiFeeReceiver,
493 | | address[] memory longTokenSwapPath,
494 | | address[] memory shortTokenSwapPath,
495 | | uint256 minMarketTokens,
496 | | bool shouldUnwrapNativeToken,
497 | | uint256 executionFee,
498 | | uint256 callbackGasLimit
499 | * | ) internal returns (DepositParams memory) {
500 | * | DepositParams memory depositParams = DepositParams({
501 | * | receiver: receiver,
502 | * | callbackContract: callbackContract,
503 | * | uiFeeReceiver: uiFeeReceiver,
504 | * | longTokenSwapPath: longTokenSwapPath,
505 | * | shortTokenSwapPath: shortTokenSwapPath,
506 | * | minMarketTokens: minMarketTokens,
507 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken,
508 | * | executionFee: executionFee,
509 | * | callbackGasLimit: callbackGasLimit
510 | | });
511 | |
512 | * | return depositParams;
513 | | }
514 | |
515 | * | function _setDepositParams(
516 | | DepositParams memory depositParams,
517 | | Market.Props memory marketProps
518 | * | ) internal returns (DepositUtils.CreateDepositParams memory) {
519 | * | DepositUtils.CreateDepositParams memory createDepositParams;
520 | * | createDepositParams.receiver = depositParams.receiver;
521 | * | createDepositParams.callbackContract = depositParams.callbackContract;
522 | * | createDepositParams.uiFeeReceiver = depositParams.uiFeeReceiver;
523 | * | createDepositParams.market = marketProps.marketToken;
524 | * | createDepositParams.initialLongToken = marketProps.longToken;
525 | * | createDepositParams.initialShortToken = marketProps.shortToken;
526 | * | createDepositParams.longTokenSwapPath = depositParams.longTokenSwapPath;
527 | * | createDepositParams.shortTokenSwapPath = depositParams
528 | | .shortTokenSwapPath;
529 | * | createDepositParams.minMarketTokens = depositParams.minMarketTokens;
530 | * | createDepositParams.shouldUnwrapNativeToken = depositParams
531 | | .shouldUnwrapNativeToken;
532 | * | createDepositParams.executionFee = depositParams.executionFee;
533 | * | createDepositParams.callbackGasLimit = depositParams.callbackGasLimit;
534 | |
535 | * | return createDepositParams;
536 | | }
537 | | }
538 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/depositSetup/DepositSpeedup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./DepositSetup.sol";
6 | |
7 | | contract DepositSpeedup is DepositSetup {
8 | *r | function CreateExecuteDeposit(
9 | | uint8 marketIndex,
10 | | uint8 userIndex,
11 | | uint longAmount,
12 | | uint shortAmount,
13 | | uint priceSeed,
14 | | uint executionFee,
15 | | uint8 swapPathSeed
16 | * | ) public {
17 | * | callback.cleanETHBalance(address(0));
18 | |
19 | * | _createDeposit(
20 | * | marketIndex,
21 | * | userIndex,
22 | * | longAmount,
23 | * | shortAmount,
24 | * | priceSeed,
25 | * | SWAPS_ENABLED ? swapPathSeed : 7,
26 | * | executionFee,
27 | * | false
28 | | );
29 | * | uint before_callbackBalance_GEN2 = address(callback).balance;
30 | |
31 | * | (
32 | * | DepositCreated memory depositToExecute,
33 | * | DepositState memory afterDepositExecution
34 | * | ) = ExecuteDeposit(priceSeed, true); //isAtomicExec
35 | |
36 | * | invariantDepositedTokensMatchSimulatedAmounts(
37 | * | depositToExecute,
38 | * | afterDepositExecution
39 | | );
40 | * | invariantMarketTokenSupplyIncreases(depositToExecute);
41 | |
42 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
43 | | // address(0),
44 | | // before_callbackBalance_GEN2,
45 | | // address(callback).balance, //after
46 | | // depositToExecute.createDepositParams.executionFee
47 | | // );
48 | | }
49 | |
50 | *r | function CreateCancelDeposit(
51 | | uint8 marketIndex,
52 | | uint8 userIndex,
53 | | uint longAmount,
54 | | uint shortAmount,
55 | | uint priceSeed,
56 | | uint8 swapPathSeed,
57 | | uint executionFee
58 | | ) public {
59 | * | _createDeposit(
60 | * | marketIndex,
61 | * | userIndex,
62 | * | longAmount,
63 | * | shortAmount,
64 | * | priceSeed,
65 | * | SWAPS_ENABLED ? swapPathSeed : 7,
66 | * | executionFee,
67 | * | false
68 | | );
69 | |
70 | | (
71 | * | DepositState memory _before,
72 | * | DepositState memory _after,
73 | * | DepositCreated memory depositCreated
74 | * | ) = CancelDeposit(priceSeed, true);
75 | |
76 | | _cancelDepositAssertions(_before, _after, depositCreated);
77 | | }
78 | | function CreateExecuteInitialDeposit(
79 | | uint8 marketIndex,
80 | | uint8 userIndex,
81 | | uint longAmount,
82 | | uint shortAmount,
83 | | uint priceSeed,
84 | | uint8 swapPathSeed,
85 | | uint executionFee
86 | | ) internal {
87 | | callback.cleanETHBalance(address(0));
88 | |
89 | | _createDeposit(
90 | | marketIndex,
91 | | userIndex,
92 | | longAmount,
93 | | shortAmount,
94 | | priceSeed,
95 | | SWAPS_ENABLED ? swapPathSeed : 7,
96 | | executionFee,
97 | | true //setUp has 0 gas price, so we need to skip fee coverage invariants
98 | | );
99 | | uint before_callbackBalance_GEN2 = address(callback).balance;
100 | |
101 | | (
102 | | DepositCreated memory depositToExecute,
103 | | DepositState memory afterDepositExecution
104 | | ) = ExecuteDeposit(priceSeed, true); //isAtomicExec
105 | |
106 | | invariantDepositedTokensMatchSimulatedAmounts(
107 | | depositToExecute,
108 | | afterDepositExecution
109 | | );
110 | | invariantMarketTokenSupplyIncreases(depositToExecute);
111 | |
112 | | // InvariantExecutionFeeIsAlwaysCovered(//NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
113 | | // address(0),
114 | | // before_callbackBalance_GEN2,
115 | | // address(callback).balance, //after
116 | | // depositToExecute.createDepositParams.executionFee
117 | | // );
118 | | }
119 | | function setUpDeposits(
120 | | uint8 marketIndex,
121 | | uint longAmount,
122 | | uint shortAmount
123 | | ) internal {
124 | | CreateExecuteInitialDeposit(
125 | | marketIndex,
126 | | 0,
127 | | longAmount,
128 | | shortAmount,
129 | | 5000e4,
130 | | 7,
131 | | FIXED_EXECUTION_FEE_AMOUNT
132 | | );
133 | | }
134 | | }
135 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/GMXPositionSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./OrderSetup.sol";
5 | | import "../ADLSetup.sol";
6 | |
7 | | contract GMXPositionSetup is OrderSetup, ADLSetup {
8 | | using Price for Price.Props;
9 | | OrderCreated[] internal orderCreatedArray;
10 | |
11 | | struct OrderCache {
12 | | address[] longSwapPath;
13 | | address[] swapPath;
14 | | address market;
15 | | address user;
16 | | address token;
17 | | uint decreaseSize;
18 | | uint collateralDeltaAmount;
19 | | bool isLimit;
20 | | bool isLong;
21 | | bool isStopLoss;
22 | | uint priceSeed;
23 | | uint amount;
24 | | uint leverage;
25 | | }
26 | |
27 | *r | function SwapOrder(
28 | | uint8 tokenIndex,
29 | | uint8 userIndex,
30 | | uint priceSeed,
31 | | uint amount,
32 | | uint8 swapPathSeed,
33 | | bool isLimit,
34 | | uint executionFee
35 | * | ) public {
36 | | //Introducing high execution fee, so we can judge by refunded amount after
37 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT;
38 | |
39 | * | OrderCache memory cache;
40 | |
41 | * | cache.user = _getRandomUser(userIndex);
42 | * | cache.swapPath = _getSwapPath(swapPathSeed);
43 | * | cache.token = _getRandomToken(tokenIndex);
44 | |
45 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
46 | * | (amount, ) = _getTokenAmounts(
47 | * | amount,
48 | * | 0,
49 | * | cache.token,
50 | * | address(0),
51 | * | cache.user
52 | | );
53 | |
54 | * | IBaseOrderUtils.CreateOrderParamsAddresses
55 | * | memory addresses = _setCreateOrderParamsAddresses(
56 | * | cache.user, //receiver,
57 | * | address(callback), //callbackContract
58 | * | address(0), //uiFeeReceiver
59 | * | cache.market,
60 | * | cache.token,
61 | * | cache.swapPath
62 | | );
63 | |
64 | * | IBaseOrderUtils.CreateOrderParamsNumbers
65 | * | memory numbers = _setCreateOrderParamsNumbers(
66 | * | _getUSDAmount(amount, cache.token, 1, tokenPrices), //sizeDeltaUsd
67 | * | amount, // initialCollateralDeltaAmount, native decimals
68 | * | _getTokenPrice(cache.token, tokenPrices), //triggerPrice
69 | * | 1, //acceptablePrice
70 | * | executionFee,
71 | * | 200 * 1000, //callbackGasLimit
72 | * | 1 // minOutputAmount
73 | | );
74 | |
75 | * | IBaseOrderUtils.CreateOrderParams
76 | * | memory orderParams = _setCreateOrderParams(
77 | * | addresses,
78 | * | numbers,
79 | * | isLimit
80 | * | ? Order.OrderType.LimitSwap
81 | * | : Order.OrderType.MarketSwap,
82 | * | Order.DecreasePositionSwapType.NoSwap, //hardcoded
83 | * | true, //isLong, any
84 | * | false, //no wrap to simplify assertions
85 | * | true, //auto cancel
86 | * | bytes32(0) //refferal code
87 | | );
88 | |
89 | * | _order(
90 | * | orderParams,
91 | * | swapPathSeed,
92 | * | tokenPrices,
93 | * | executionFee,
94 | * | keccak256(abi.encode(isLimit ? "SWAP_LIMIT" : "SWAP_MARKET"))
95 | | );
96 | |
97 | * | ExecuteOrder(priceSeed, true);
98 | | }
99 | |
100 | *r | function IncreaseOrder(
101 | | uint8 marketIndex,
102 | | uint8 userIndex,
103 | | uint leverageSeed,
104 | | uint priceSeed,
105 | | uint amount,
106 | | bool isLimit,
107 | | bool isLong,
108 | | uint8 swapPathSeed,
109 | | uint executionFee
110 | * | ) public {
111 | * | if (!SWAPS_ENABLED) {
112 | * | swapPathSeed = 7;
113 | | }
114 | |
115 | | //Swaps disabled
116 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT;
117 | |
118 | * | OrderCache memory cache;
119 | * | cache.user = _getRandomUser(userIndex);
120 | * | cache.longSwapPath = _getSwapPath(swapPathSeed);
121 | * | cache.market = _getMarketAddress(marketIndex);
122 | * | cache.leverage = clampBetween(leverageSeed, 1, 100);
123 | |
124 | * | if (!_checkMarketForOrders(cache.market)) {
125 | * | return;
126 | | }
127 | |
128 | * | Market.Props memory marketProps = MarketStoreUtils.get(
129 | * | dataStore,
130 | * | cache.market
131 | | );
132 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
133 | |
134 | * | cache.token = isLong ? marketProps.longToken : marketProps.shortToken;
135 | |
136 | * | if (isLong) {
137 | * | (cache.amount, ) = _getTokenAmounts(
138 | * | amount,
139 | * | 0,
140 | * | marketProps.longToken,
141 | * | marketProps.shortToken,
142 | * | cache.user
143 | | );
144 | | } else {
145 | * | (, cache.amount) = _getTokenAmounts(
146 | * | 0,
147 | * | amount,
148 | * | marketProps.longToken,
149 | * | marketProps.shortToken,
150 | * | cache.user
151 | | );
152 | | }
153 | |
154 | * | IBaseOrderUtils.CreateOrderParamsAddresses
155 | * | memory addresses = _setCreateOrderParamsAddresses(
156 | * | cache.user,
157 | * | address(callback),
158 | * | address(0), //uiFeeReceiver
159 | * | cache.market,
160 | * | cache.token,
161 | * | cache.longSwapPath
162 | | );
163 | |
164 | * | IBaseOrderUtils.CreateOrderParamsNumbers
165 | * | memory numbers = _setCreateOrderParamsNumbers(
166 | * | _getUSDAmount(
167 | * | cache.amount,
168 | * | cache.token,
169 | * | cache.leverage,
170 | * | tokenPrices
171 | | ),
172 | * | cache.amount, // initialCollateralDeltaAmount, native decimals
173 | * | _getTokenPrice(marketProps.indexToken, tokenPrices), //triggerPrice
174 | * | isLong ? type(uint256).max : 1, //acceptable price
175 | * | executionFee,
176 | * | 200 * 1000, //'callbackGasLimit
177 | * | 1 // minOutputAmount
178 | | );
179 | |
180 | * | IBaseOrderUtils.CreateOrderParams
181 | * | memory orderParams = _setCreateOrderParams(
182 | * | addresses,
183 | * | numbers,
184 | * | isLimit
185 | * | ? Order.OrderType.LimitIncrease
186 | * | : Order.OrderType.MarketIncrease,
187 | * | Order.DecreasePositionSwapType.NoSwap, //hardcoded
188 | * | isLong, //isLong
189 | * | false, //no wrap to simplify assertions
190 | * | true, //auto cancel
191 | * | bytes32(0) //refferal code
192 | | );
193 | |
194 | * | _order(
195 | * | orderParams,
196 | * | swapPathSeed,
197 | * | tokenPrices,
198 | * | executionFee,
199 | * | keccak256(abi.encode(isLong ? "INCREASE_LONG" : "INCREASE_SHORT"))
200 | | );
201 | | }
202 | |
203 | * | function DecreasePosition(
204 | | uint8 marketIndex,
205 | | uint8 userIndex,
206 | | uint priceSeed,
207 | | uint collateralDeltaSeed,
208 | | bool closePosition,
209 | | bool isLimit,
210 | | bool isLong,
211 | | bool isStopLoss,
212 | | uint8 swapPathSeed,
213 | | uint executionFee
214 | * | ) public {
215 | * | if (!SWAPS_ENABLED) {
216 | * | swapPathSeed = 7;
217 | | }
218 | |
219 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT;
220 | |
221 | * | OrderCache memory cache;
222 | * | cache.isLong = isLong;
223 | * | cache.isLimit = isLimit;
224 | * | cache.isStopLoss = isStopLoss;
225 | * | cache.priceSeed = priceSeed;
226 | * | cache.longSwapPath = _getSwapPath(swapPathSeed);
227 | * | cache.market = _getMarketAddress(marketIndex);
228 | * | cache.user = _getRandomUser(userIndex);
229 | |
230 | * | if (!_checkMarketForOrders(cache.market)) {
231 | * | return;
232 | | }
233 | |
234 | * | Market.Props memory marketProps = MarketStoreUtils.get(
235 | * | dataStore,
236 | * | cache.market
237 | | );
238 | * | TokenPrices memory tokenPrices = _setTokenPrices(cache.priceSeed);
239 | |
240 | * | cache.token = cache.isLong
241 | * | ? marketProps.longToken
242 | * | : marketProps.shortToken;
243 | |
244 | * | bytes32 positionKey = Position.getPositionKey(
245 | * | cache.user,
246 | * | cache.market,
247 | * | cache.token,
248 | * | cache.isLong
249 | | );
250 | |
251 | * | Position.Props memory position = PositionStoreUtils.get(
252 | * | dataStore,
253 | * | positionKey
254 | | );
255 | |
256 | * | if (
257 | * | position.numbers.sizeInUsd == 0 &&
258 | * | position.numbers.sizeInTokens == 0 &&
259 | * | position.numbers.collateralAmount == 0
260 | | ) {
261 | * | return;
262 | | }
263 | |
264 | * | IBaseOrderUtils.CreateOrderParamsAddresses
265 | * | memory addresses = _setCreateOrderParamsAddresses(
266 | * | cache.user,
267 | * | address(callback),
268 | * | address(0), //uiFeeReceiver
269 | * | cache.market,
270 | * | cache.token,
271 | * | cache.longSwapPath
272 | | );
273 | |
274 | * | if (closePosition) {
275 | * | cache.decreaseSize = position.numbers.sizeInUsd;
276 | * | cache.collateralDeltaAmount = 0;
277 | | } else {
278 | * | cache.decreaseSize = clampBetween(
279 | * | collateralDeltaSeed,
280 | * | 1,
281 | * | position.numbers.sizeInUsd -
282 | | DECREASE_POSITION_TOLERABLE_PRICE_SUB
283 | | );
284 | * | cache.collateralDeltaAmount = clampBetween(
285 | * | collateralDeltaSeed / RANDOMIZER_DIVISOR,
286 | * | 1,
287 | * | position.numbers.collateralAmount
288 | | );
289 | |
290 | *r | require( //The idea is to prevent 0 out if size decrease delta is too small
291 | * | cache.decreaseSize > DECREASE_POSITION_DELTA_MIN,
292 | | "DecreasePosition only by delta amount min"
293 | | );
294 | | }
295 | |
296 | * | IBaseOrderUtils.CreateOrderParamsNumbers
297 | * | memory numbers = _setCreateOrderParamsNumbers(
298 | * | cache.decreaseSize,
299 | * | cache.collateralDeltaAmount,
300 | * | _getTokenPrice(marketProps.indexToken, tokenPrices), //triggerPrice
301 | * | cache.isLong ? 0 : type(uint256).max, // acceptable price
302 | * | 0, // execution fee
303 | * | 200 * 1000, //'callbackGasLimit
304 | * | 1 // minOutput
305 | | );
306 | |
307 | * | IBaseOrderUtils.CreateOrderParams
308 | * | memory orderParams = _setCreateOrderParams(
309 | * | addresses,
310 | * | numbers,
311 | * | cache.isStopLoss
312 | * | ? Order.OrderType.StopLossDecrease
313 | * | : cache.isLimit
314 | * | ? Order.OrderType.LimitDecrease
315 | * | : Order.OrderType.MarketDecrease,
316 | * | Order.DecreasePositionSwapType.NoSwap, //hadrcoded
317 | * | cache.isLong,
318 | * | false, //no wrap to simplify assertions
319 | * | true, //auto cancel
320 | * | bytes32(0) //refferal code
321 | | );
322 | |
323 | * | if (closePosition) {
324 | * | _order(
325 | * | orderParams,
326 | * | swapPathSeed,
327 | * | tokenPrices,
328 | * | 0,
329 | * | keccak256(abi.encode("CLOSE"))
330 | | );
331 | | } else {
332 | * | _order(
333 | * | orderParams,
334 | * | swapPathSeed,
335 | * | tokenPrices,
336 | * | 0,
337 | * | keccak256(abi.encode("DECREASE"))
338 | | );
339 | | //Not doing separate handler for stop losses because technically its also a decrease
340 | | }
341 | | }
342 | |
343 | * | function _order(
344 | | IBaseOrderUtils.CreateOrderParams memory params,
345 | | uint8 swapPathSeed,
346 | | TokenPrices memory tokenPrices,
347 | | uint executionFee,
348 | | bytes32 handlerType
349 | * | ) internal returns (OrderCreated memory orderCreated) {
350 | * | if (
351 | | //Swap Order
352 | * | handlerType == keccak256(abi.encode("SWAP_LIMIT")) ||
353 | * | handlerType == keccak256(abi.encode("SWAP_MARKET"))
354 | | ) {
355 | * | _mintAndSendTokensTo(
356 | * | params.addresses.receiver,
357 | * | address(orderVault), //to
358 | * | params.numbers.initialCollateralDeltaAmount, //longTokenAmount
359 | * | 0, //shortTokenAmount
360 | * | params.addresses.initialCollateralToken, //longTokenAddress
361 | * | address(0), //shortTokenAddress
362 | * | executionFee,
363 | * | false //isWETH
364 | | );
365 | * | } else {
366 | | //Increase and Decrease Order
367 | * | Market.Props memory marketProps = MarketStoreUtils.get(
368 | * | dataStore,
369 | * | params.addresses.market
370 | | );
371 | |
372 | * | bool isWeth = marketProps.longToken == address(WETH) ||
373 | * | marketProps.shortToken == address(WETH);
374 | |
375 | * | uint256 longAmount = params.isLong
376 | * | ? params.numbers.initialCollateralDeltaAmount
377 | * | : 0;
378 | * | uint256 shortAmount = params.isLong
379 | * | ? 0
380 | * | : params.numbers.initialCollateralDeltaAmount;
381 | |
382 | | //Transfer only if Increasing
383 | * | if (
384 | * | handlerType ==
385 | * | keccak256(
386 | * | abi.encode(
387 | * | params.isLong ? "INCREASE_LONG" : "INCREASE_SHORT"
388 | | )
389 | | )
390 | | ) {
391 | * | if (params.isLong) {
392 | * | _mintAndSendTokensTo(
393 | * | params.addresses.receiver,
394 | * | address(orderVault),
395 | * | longAmount,
396 | * | shortAmount,
397 | * | marketProps.longToken,
398 | * | address(0), //shortTokenAddress
399 | * | executionFee,
400 | * | isWeth
401 | | );
402 | | } else {
403 | * | _mintAndSendTokensTo(
404 | * | params.addresses.receiver,
405 | * | address(orderVault),
406 | * | longAmount,
407 | * | shortAmount,
408 | * | address(0), //longTokenAddress
409 | * | marketProps.shortToken,
410 | * | executionFee,
411 | * | isWeth
412 | | );
413 | | }
414 | | }
415 | | }
416 | |
417 | * | bytes memory callData_CreateOrder = abi.encodeWithSelector(
418 | * | exchangeRouter.createOrder.selector,
419 | * | params
420 | | );
421 | |
422 | * | vm.prank(params.addresses.receiver);
423 | |
424 | * | (
425 | * | bool success_CreateOrder,
426 | * | bytes memory returnData_CreateOrder
427 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(callData_CreateOrder);
428 | |
429 | * | if (!success_CreateOrder) {
430 | * | invariantDoesNotSilentRevert(returnData_CreateOrder);
431 | | } else {
432 | * | orderCreated.key = abi.decode(returnData_CreateOrder, (bytes32));
433 | | }
434 | |
435 | * | orderCreated.createOrderParams = params;
436 | * | orderCreated.updatedAt = block.timestamp;
437 | * | orderCreated.user = params.addresses.receiver;
438 | * | orderCreated.handlerType = handlerType;
439 | * | orderCreated.amountSent = params.numbers.initialCollateralDeltaAmount;
440 | * | orderCreated.isClose = handlerType == keccak256(abi.encode("CLOSE"));
441 | * | orderCreated.swapPathSeed = swapPathSeed;
442 | * | orderCreated.tokenPrices = tokenPrices;
443 | * | orderCreated.executionFee = executionFee;
444 | * | orderCreatedArray.push(orderCreated);
445 | |
446 | * | _checkOrderCreatedCoverage(orderCreated);
447 | | }
448 | |
449 | *r | function CancelOrder(
450 | | uint seed,
451 | | bool isAtomicExec
452 | | )
453 | | public
454 | | returns (
455 | * | PositionState memory _before,
456 | * | PositionState memory _after,
457 | * | OrderCreated memory orderToCancel
458 | | )
459 | | {
460 | *r | require(orderCreatedArray.length > 0, "No orders available to cancel");
461 | |
462 | * | uint256 randomIndex = isAtomicExec
463 | * | ? orderCreatedArray.length - 1
464 | * | : clampBetween(seed, 0, orderCreatedArray.length - 1);
465 | * | orderToCancel = orderCreatedArray[randomIndex];
466 | |
467 | * | fl.neq(
468 | * | uint(orderToCancel.key),
469 | * | uint(0),
470 | | "Order key is zero and orderToCancel exists"
471 | | );
472 | |
473 | * | _before = _snapPositionState(orderToCancel.key, orderToCancel);
474 | |
475 | * | bytes memory callData_CancelOrder = abi.encodeWithSelector(
476 | * | exchangeRouter.cancelOrder.selector,
477 | * | orderToCancel.key
478 | | );
479 | |
480 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
481 | * | vm.prank(orderToCancel.user);
482 | |
483 | * | (
484 | * | bool success_CancelOrder,
485 | * | bytes memory returnData_CancelOrder
486 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(callData_CancelOrder);
487 | |
488 | * | if (!success_CancelOrder) {
489 | * | invariantDoesNotSilentRevert(returnData_CancelOrder);
490 | | }
491 | |
492 | | _after = _snapPositionState(orderToCancel.key, orderToCancel);
493 | |
494 | | _checkOrderCancelCoverage(orderToCancel);
495 | | }
496 | |
497 | *r | function ExecuteOrder(uint priceSeed, bool isAtomicExec) public {
498 | * | callback.cleanETHBalance(address(0));
499 | |
500 | *r | require(orderCreatedArray.length > 0, "No orders available to execute");
501 | |
502 | * | uint256 randomIndex = isAtomicExec
503 | * | ? orderCreatedArray.length - 1
504 | * | : clampBetween(priceSeed, 0, orderCreatedArray.length - 1);
505 | |
506 | * | OrderCreated memory orderToExecute = orderCreatedArray[randomIndex];
507 | |
508 | * | Market.Props memory marketProps;
509 | * | bytes32 positionKey;
510 | |
511 | * | if (orderToExecute.createOrderParams.addresses.market != address(0)) {
512 | * | marketProps = MarketStoreUtils.get(
513 | * | dataStore,
514 | * | orderToExecute.createOrderParams.addresses.market
515 | | );
516 | * | positionKey = Position.getPositionKey(
517 | * | orderToExecute.user,
518 | * | marketProps.marketToken,
519 | * | orderToExecute.createOrderParams.isLong
520 | * | ? marketProps.longToken
521 | * | : marketProps.shortToken,
522 | * | orderToExecute.createOrderParams.isLong
523 | | );
524 | | }
525 | |
526 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
527 | |
528 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
529 | * | tokenPrices.tokens,
530 | * | tokenPrices.maxPrices,
531 | * | tokenPrices.minPrices
532 | | );
533 | |
534 | * | uint before_callbackBalance_GEN2 = address(callback).balance;
535 | |
536 | * | if (positionKey != 0) {
537 | | /*
538 | | __
539 | | <(o )___
540 | | ( ._> /
541 | | `---' Increase and Decrease Order
542 | | */
543 | |
544 | * | PositionState memory _before = _snapPositionState(
545 | * | positionKey,
546 | * | orderToExecute
547 | | );
548 | * | _executeOrderGMX(orderToExecute.key, oracleParams);
549 | * | PositionState memory _after = _snapPositionState(
550 | * | positionKey,
551 | * | orderToExecute
552 | | );
553 | |
554 | * | Position.Props memory position = PositionStoreUtils.get(
555 | * | dataStore,
556 | * | positionKey
557 | | );
558 | |
559 | * | if (
560 | * | orderToExecute.createOrderParams.orderType ==
561 | * | Order.OrderType.MarketIncrease ||
562 | * | orderToExecute.createOrderParams.orderType ==
563 | * | Order.OrderType.LimitIncrease
564 | | ) {
565 | * | if (position.numbers.sizeInUsd != 0) {
566 | | //if position opened
567 | * | checkOrderAndGetCoverage(
568 | * | positionKey,
569 | * | marketProps,
570 | * | tokenPrices,
571 | * | true // isIncreaseOrder
572 | | );
573 | * | _increaseAssertions(_before, _after, orderToExecute);
574 | | if (isAtomicExec) {
575 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
576 | | // address(0),
577 | | // before_callbackBalance_GEN2,
578 | | // address(callback).balance, //after
579 | | // orderToExecute
580 | | // .createOrderParams
581 | | // .numbers
582 | | // .executionFee
583 | | // );
584 | | }
585 | | }
586 | | }
587 | |
588 | * | if (
589 | * | orderToExecute.createOrderParams.orderType ==
590 | * | Order.OrderType.MarketDecrease ||
591 | * | orderToExecute.createOrderParams.orderType ==
592 | * | Order.OrderType.LimitDecrease
593 | | ) {
594 | | if (position.numbers.sizeInUsd != 0) {
595 | | //if not closed
596 | | checkOrderAndGetCoverage(
597 | | positionKey,
598 | | marketProps,
599 | | tokenPrices,
600 | | false // isIncreaseOrder
601 | | );
602 | | }
603 | | _decreaseAssertions(_before, _after, orderToExecute);
604 | |
605 | | if (isAtomicExec) {
606 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
607 | | // address(0),
608 | | // before_callbackBalance_GEN2,
609 | | // address(callback).balance, //after
610 | | // orderToExecute.createOrderParams.numbers.executionFee
611 | | // );
612 | | }
613 | | }
614 | * | } else {
615 | | /*
616 | | __
617 | | <(o )___
618 | | ( ._> /
619 | | `---' Swap Order
620 | | */
621 | |
622 | * | SwapState memory _before = _snapSwapState(false, orderToExecute);
623 | * | _executeOrderGMX(orderToExecute.key, oracleParams);
624 | * | SwapState memory _after = _snapSwapState(true, orderToExecute);
625 | |
626 | *r | require(
627 | * | _after.balanceOfOutputToken > _before.balanceOfOutputToken,
628 | | "Swap: state was not changed"
629 | | );
630 | |
631 | * | _swapAssertions(_before, _after, orderToExecute);
632 | | if (isAtomicExec) {
633 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
634 | | // address(0),
635 | | // before_callbackBalance_GEN2,
636 | | // address(callback).balance, //after
637 | | // orderToExecute.createOrderParams.numbers.executionFee
638 | | // );
639 | | }
640 | | }
641 | |
642 | * | orderCreatedArray[randomIndex] = orderCreatedArray[
643 | * | orderCreatedArray.length - 1
644 | | ];
645 | * | orderCreatedArray.pop();
646 | | }
647 | * | function _executeOrderGMX(
648 | | bytes32 orderKey,
649 | | OracleUtils.SetPricesParams memory oracleParams
650 | * | ) internal {
651 | * | bytes memory callData_ExecuteOrder = abi.encodeWithSelector(
652 | * | orderHandler.executeOrder.selector,
653 | * | orderKey,
654 | * | oracleParams
655 | | );
656 | * | vm.prank(DEPLOYER);
657 | |
658 | * | (
659 | * | bool success_ExecuteOrder,
660 | * | bytes memory returnData_ExecuteOrder
661 | * | ) = address(orderHandler).call{gas: 30_000_000}(callData_ExecuteOrder);
662 | |
663 | * | if (!success_ExecuteOrder) {
664 | * | invariantDoesNotSilentRevert(returnData_ExecuteOrder);
665 | | }
666 | | }
667 | |
668 | | function getOrderKeys(
669 | | uint256 start,
670 | | uint256 end
671 | | ) internal view returns (bytes32[] memory) {
672 | | bytes32 ORDER_LIST_KEY = keccak256(abi.encode("ORDER_LIST"));
673 | | return dataStore.getBytes32ValuesAt(ORDER_LIST_KEY, start, end);
674 | | }
675 | * | function _checkMarketForOrders(address market) internal returns (bool) {
676 | * | return market == market_0_WETH_USDC ? false : true;
677 | | }
678 | |
679 | * | function checkOrderAndGetCoverage(
680 | | bytes32 positionKey,
681 | | Market.Props memory marketProps,
682 | | TokenPrices memory tokenPrices,
683 | | bool isIncreaseOrder
684 | * | ) internal {
685 | * | Position.Props memory position = PositionStoreUtils.get(
686 | * | dataStore,
687 | * | positionKey
688 | | );
689 | |
690 | * | if (position.numbers.sizeInUsd != 0) {
691 | *r | ReaderUtils.PositionInfo memory positionInfo = reader
692 | | .getPositionInfo(
693 | * | dataStore,
694 | * | referralStorage,
695 | * | positionKey,
696 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
697 | * | 0, // size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true
698 | * | address(0),
699 | * | true // usePositionSizeAsSizeDeltaUsd
700 | | );
701 | * | ReaderUtils.MarketInfo memory marketInfo = reader.getMarketInfo(
702 | * | dataStore,
703 | * | _getMarketPrices(marketProps.marketToken, tokenPrices),
704 | * | marketProps.marketToken
705 | | );
706 | * | if (isIncreaseOrder) {
707 | * | _checkIncreaseOrderAndGetPositionCoverage(position); //position info checked separately
708 | * | _checkIncreaseOrderAndGetPositionInfoCoverage(positionInfo);
709 | * | _checkIncreaseOrderAndGetMarketInfoCoverage(marketInfo);
710 | | } else {
711 | | _checkDecreaseOrderAndGetPositionCoverage(position);
712 | | _checkDecreaseOrderAndGetPositionInfoCoverage(positionInfo);
713 | | _checkDecreaseOrderAndGetMarketInfoCoverage(marketInfo);
714 | | }
715 | | }
716 | | }
717 | * | function _getUSDAmount(
718 | | uint amount,
719 | | address token,
720 | | uint leverage,
721 | | TokenPrices memory tokenPrices
722 | * | ) internal returns (uint result) {
723 | * | if (token == address(USDT) || token == address(USDC)) {
724 | * | result = amount * leverage * 1e24; //NOTE: hardcoded precision
725 | * | } else {
726 | * | uint tokenPrice = _getTokenPrice(token, tokenPrices);
727 | * | result = amount * leverage * tokenPrice;
728 | | }
729 | | }
730 | | }
731 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/GMXPositionSpeedup.sol
1 | | pragma solidity ^0.8.0;
2 | |
3 | | import "./GMXPositionSetup.sol";
4 | |
5 | | contract GMXPositionSpeedup is GMXPositionSetup {
6 | *r | function IncreaseAndCancelOrder(
7 | | uint8 marketIndex,
8 | | uint8 userIndex,
9 | | uint leverageSeed,
10 | | uint priceSeed,
11 | | uint amount,
12 | | bool isLong,
13 | | uint8 swapPathSeed,
14 | | uint executionFee
15 | | ) public {
16 | * | IncreaseOrder(
17 | * | marketIndex,
18 | * | userIndex,
19 | * | leverageSeed,
20 | * | priceSeed,
21 | * | amount,
22 | * | false,
23 | * | isLong,
24 | * | swapPathSeed,
25 | * | executionFee
26 | | );
27 | | (
28 | * | PositionState memory _before,
29 | * | PositionState memory _after,
30 | * | OrderCreated memory orderToCancel
31 | * | ) = CancelOrder(priceSeed, true);
32 | |
33 | | _cancelOrderAssertions(_before, _after, orderToCancel);
34 | | }
35 | |
36 | *r | function DecreaseCloseLongShortOrder(
37 | | uint8 marketIndex,
38 | | uint8 userIndex,
39 | | uint leverageSeed,
40 | | uint priceSeed,
41 | | uint amount,
42 | | uint collateralDeltaSeed,
43 | | bool isLong,
44 | | bool isStopLoss,
45 | | bool closePosition,
46 | | uint8 swapPathSeed,
47 | | uint executionFee
48 | | ) public {
49 | * | IncreaseOrder(
50 | * | marketIndex,
51 | * | userIndex,
52 | * | leverageSeed,
53 | * | priceSeed,
54 | * | amount,
55 | * | false,
56 | * | isLong,
57 | * | swapPathSeed,
58 | * | executionFee
59 | | );
60 | |
61 | * | ExecuteOrder(priceSeed, true); //last item
62 | |
63 | * | DecreasePosition(
64 | * | marketIndex,
65 | * | userIndex,
66 | * | priceSeed,
67 | * | collateralDeltaSeed,
68 | * | closePosition,
69 | * | false, //isLimit
70 | * | isLong,
71 | * | isStopLoss,
72 | * | swapPathSeed,
73 | * | executionFee
74 | | );
75 | * | ExecuteOrder(priceSeed, true); //last item
76 | | }
77 | |
78 | *r | function IncreaseExecuteLimitOrder(
79 | | uint8 marketIndex,
80 | | uint8 userIndex,
81 | | uint leverageSeed,
82 | | uint priceSeed,
83 | | uint amount,
84 | | bool isLong,
85 | | uint8 swapPathSeed,
86 | | uint executionFee
87 | | ) public {
88 | * | IncreaseOrder(
89 | * | marketIndex,
90 | * | userIndex,
91 | * | leverageSeed,
92 | * | priceSeed,
93 | * | amount,
94 | * | true,
95 | * | isLong,
96 | * | swapPathSeed,
97 | * | executionFee
98 | | ); //7 is emply swap path
99 | * | ExecuteOrder(priceSeed, true); //last item
100 | | }
101 | |
102 | *r | function DecreaseExecuteLimitOrderLong(
103 | | uint8 marketIndex,
104 | | uint8 userIndex,
105 | | uint leverageSeed,
106 | | uint priceSeed,
107 | | uint amount,
108 | | uint collateralDeltaSeed,
109 | | bool isStopLoss,
110 | | bool closePosition,
111 | | uint8 swapPathSeed,
112 | | uint executionFee
113 | | ) public {
114 | * | IncreaseOrder(
115 | * | marketIndex,
116 | * | userIndex,
117 | * | leverageSeed,
118 | * | priceSeed,
119 | * | amount,
120 | * | false,
121 | * | true,
122 | * | swapPathSeed,
123 | * | executionFee
124 | | ); //7 is emply swap path
125 | * | ExecuteOrder(priceSeed, true); //last item
126 | |
127 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
128 | |
129 | * | DecreasePosition(
130 | * | marketIndex,
131 | * | userIndex,
132 | * | priceSeed,
133 | * | collateralDeltaSeed,
134 | * | closePosition,
135 | * | true,
136 | * | true,
137 | * | isStopLoss,
138 | * | swapPathSeed, //7 is emply swap path
139 | * | executionFee
140 | | );
141 | |
142 | * | ExecuteOrder(priceSeed, true); //last item
143 | | }
144 | *r | function DecreaseExecuteLimitOrderShort(
145 | | uint8 marketIndex,
146 | | uint8 userIndex,
147 | | uint leverageSeed,
148 | | uint priceSeed,
149 | | uint amount,
150 | | uint collateralDeltaSeed,
151 | | bool isStopLoss,
152 | | bool closePosition,
153 | | uint8 swapPathSeed,
154 | | uint executionFee
155 | | ) public {
156 | * | IncreaseOrder(
157 | * | marketIndex,
158 | * | userIndex,
159 | * | leverageSeed,
160 | * | priceSeed,
161 | * | amount,
162 | * | true,
163 | * | false,
164 | * | swapPathSeed,
165 | * | executionFee
166 | | ); //7 is emply swap path
167 | * | ExecuteOrder(priceSeed, true); //last item
168 | |
169 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
170 | |
171 | * | DecreasePosition(
172 | * | marketIndex,
173 | * | userIndex,
174 | * | priceSeed,
175 | * | collateralDeltaSeed,
176 | * | closePosition,
177 | * | true,
178 | * | false,
179 | * | isStopLoss,
180 | * | swapPathSeed, //7 is emply swap path
181 | * | executionFee
182 | | );
183 | * | ExecuteOrder(priceSeed, true); //last item
184 | | }
185 | |
186 | *r | function DecreaseExecuteLimitOrderShortWithSwap(
187 | | uint8 marketIndex,
188 | | uint8 userIndex,
189 | | uint leverageSeed,
190 | | uint priceSeed,
191 | | uint amount,
192 | | uint collateralDeltaSeed,
193 | | bool closePosition,
194 | | bool isStopLoss,
195 | | uint8 swapPathSeed,
196 | | uint executionFee
197 | | ) public {
198 | * | IncreaseOrder(
199 | * | marketIndex,
200 | * | userIndex,
201 | * | leverageSeed,
202 | * | priceSeed,
203 | * | amount,
204 | * | true,
205 | * | false,
206 | * | swapPathSeed,
207 | * | executionFee
208 | | );
209 | * | ExecuteOrder(priceSeed, true); //last item
210 | |
211 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
212 | |
213 | * | DecreasePosition(
214 | * | marketIndex,
215 | * | userIndex,
216 | * | priceSeed,
217 | * | collateralDeltaSeed,
218 | * | closePosition,
219 | * | true,
220 | * | false,
221 | * | isStopLoss,
222 | * | swapPathSeed,
223 | * | executionFee
224 | | );
225 | * | ExecuteOrder(priceSeed, true); //last item
226 | | }
227 | |
228 | *r | function OrderAndADL(
229 | | uint8 marketIndex,
230 | | uint8 userIndex,
231 | | uint leverageSeed,
232 | | uint priceSeed,
233 | | uint amount,
234 | | bool isLong,
235 | | uint8 swapPathSeed,
236 | | uint executionFee
237 | | ) public {
238 | | //Here we creating specific conditions to cover ADL once, later we check if fuzzer reached this conditions itself
239 | * | IncreaseExecuteLimitOrder(
240 | * | 0,
241 | * | 0,
242 | * | 10,
243 | * | 1000e4,
244 | * | 249e17, //49.99% of weth/weth/usdc market
245 | * | true,
246 | * | swapPathSeed,
247 | * | executionFee
248 | | );
249 | * | ExecuteADL(0, 999999e4);
250 | | }
251 | | }
252 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/OrderSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | | import "../../../contracts/order/BaseOrderUtils.sol";
3 | | pragma solidity ^0.8.0;
4 | * | contract OrderSetup {
5 | * | function _setCreateOrderParamsAddresses(
6 | | address receiver,
7 | | address callbackContract,
8 | | address uiFeeReceiver,
9 | | address market,
10 | | address initialCollateralToken,
11 | | address[] memory swapPath
12 | | )
13 | | internal
14 | | pure
15 | * | returns (IBaseOrderUtils.CreateOrderParamsAddresses memory)
16 | | {
17 | * | return
18 | * | IBaseOrderUtils.CreateOrderParamsAddresses({
19 | * | receiver: receiver,
20 | * | cancellationReceiver: receiver,
21 | * | callbackContract: callbackContract,
22 | * | uiFeeReceiver: uiFeeReceiver,
23 | * | market: market,
24 | * | initialCollateralToken: initialCollateralToken,
25 | * | swapPath: swapPath
26 | | });
27 | | }
28 | |
29 | * | function _setCreateOrderParamsNumbers(
30 | | uint256 sizeDeltaUsd,
31 | | uint256 initialCollateralDeltaAmount,
32 | | uint256 triggerPrice,
33 | | uint256 acceptablePrice,
34 | | uint256 executionFee,
35 | | uint256 callbackGasLimit,
36 | | uint256 minOutputAmount
37 | * | ) internal pure returns (IBaseOrderUtils.CreateOrderParamsNumbers memory) {
38 | * | return
39 | * | IBaseOrderUtils.CreateOrderParamsNumbers({
40 | * | sizeDeltaUsd: sizeDeltaUsd,
41 | * | initialCollateralDeltaAmount: initialCollateralDeltaAmount,
42 | * | triggerPrice: triggerPrice,
43 | * | acceptablePrice: acceptablePrice,
44 | * | executionFee: executionFee,
45 | * | callbackGasLimit: callbackGasLimit,
46 | * | minOutputAmount: minOutputAmount
47 | | });
48 | | }
49 | |
50 | * | function _setCreateOrderParams(
51 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses,
52 | | IBaseOrderUtils.CreateOrderParamsNumbers memory numbers,
53 | | Order.OrderType orderType,
54 | | Order.DecreasePositionSwapType decreasePositionSwapType,
55 | | bool isLong,
56 | | bool shouldUnwrapNativeToken,
57 | | bool autoCancel,
58 | | bytes32 referralCode
59 | * | ) internal pure returns (IBaseOrderUtils.CreateOrderParams memory) {
60 | * | return
61 | * | IBaseOrderUtils.CreateOrderParams({
62 | * | addresses: addresses,
63 | * | numbers: numbers,
64 | * | orderType: orderType,
65 | * | decreasePositionSwapType: decreasePositionSwapType,
66 | * | isLong: isLong,
67 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken,
68 | * | autoCancel: autoCancel,
69 | * | referralCode: referralCode
70 | | });
71 | | }
72 | |
73 | | function _setMarketPrices(
74 | | uint256 indexTokenPriceMin,
75 | | uint256 indexTokenPriceMax,
76 | | uint256 longTokenPriceMin,
77 | | uint256 longTokenPriceMax,
78 | | uint256 shortTokenPriceMin,
79 | | uint256 shortTokenPriceMax
80 | | ) internal pure returns (MarketUtils.MarketPrices memory) {
81 | | MarketUtils.MarketPrices memory prices;
82 | | prices.indexTokenPrice = Price.Props(
83 | | indexTokenPriceMin,
84 | | indexTokenPriceMax
85 | | );
86 | | prices.longTokenPrice = Price.Props(
87 | | longTokenPriceMin,
88 | | longTokenPriceMax
89 | | );
90 | | prices.shortTokenPrice = Price.Props(
91 | | shortTokenPriceMin,
92 | | shortTokenPriceMax
93 | | );
94 | |
95 | | return prices;
96 | | }
97 | | }
98 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/PositionSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "./OrderSetup.sol";
5 | | import "../ADLSetup.sol";
6 | |
7 | | contract PositionSetup is OrderSetup, ADLSetup {
8 | | using Price for Price.Props;
9 | |
10 | | // Function to generate calldata for both exchanges
11 | * | function generateBothExchangesCalldata(
12 | | uint8 seed,
13 | | bool isCollateralToIndex,
14 | | uint priceSeed,
15 | | uint amount
16 | * | ) internal returns (bytes[] memory) {
17 | * | (address vault, uint leverage, address market, ) = _gamma_getVault(
18 | * | seed
19 | | );
20 | |
21 | * | Market.Props memory marketProps = MarketStoreUtils.get(
22 | * | dataStore,
23 | * | market
24 | | );
25 | * | address tokenIn = isCollateralToIndex
26 | | ? marketProps.shortToken
27 | * | : marketProps.indexToken;
28 | |
29 | * | address tokenOut = isCollateralToIndex
30 | | ? marketProps.indexToken
31 | * | : marketProps.shortToken;
32 | |
33 | * | bytes[] memory exchangesData = new bytes[](2);
34 | * | uint256 halfAmount = amount / 2;
35 | * | uint256 remainingAmount = amount - halfAmount;
36 | |
37 | * | exchangesData[0] = constructSwapCalldata(
38 | * | tokenIn,
39 | * | tokenOut,
40 | * | halfAmount,
41 | * | 1,
42 | * | vault
43 | | );
44 | * | exchangesData[1] = constructGMXCalldata(seed, remainingAmount);
45 | * | return exchangesData;
46 | | }
47 | |
48 | | // Function to generate calldata for a single exchange
49 | * | function generateSingleExchangeCalldata(
50 | | bool onlyParaswap,
51 | | uint8 seed,
52 | | bool isCollateralToIndex,
53 | | uint amount
54 | * | ) internal returns (bytes[] memory) {
55 | * | (address vault, uint leverage, address market, ) = _gamma_getVault(
56 | * | seed
57 | | );
58 | |
59 | * | Market.Props memory marketProps = MarketStoreUtils.get(
60 | * | dataStore,
61 | * | market
62 | | );
63 | * | address tokenIn = isCollateralToIndex
64 | * | ? marketProps.shortToken
65 | * | : marketProps.indexToken;
66 | |
67 | * | address tokenOut = isCollateralToIndex
68 | * | ? marketProps.indexToken
69 | * | : marketProps.shortToken;
70 | |
71 | * | bytes[] memory exchangesData = new bytes[](1);
72 | * | if (onlyParaswap) {
73 | | exchangesData[0] = constructSwapCalldata(
74 | | tokenIn,
75 | | tokenOut,
76 | | amount,
77 | | 1,
78 | | vault
79 | | );
80 | | } else {
81 | * | exchangesData[0] = constructGMXCalldata(seed, amount);
82 | | }
83 | |
84 | * | return exchangesData;
85 | | }
86 | |
87 | * | function generateAcceptablePriceExchangeCalldata(
88 | | bool includeSwap,
89 | | uint8 seed,
90 | | bool isCollateralToIndex,
91 | | uint amount,
92 | | bool isLong
93 | * | ) internal returns (bytes[] memory) {
94 | * | (address vault, uint leverage, address market, ) = _gamma_getVault(
95 | * | seed
96 | | );
97 | |
98 | * | Market.Props memory marketProps = MarketStoreUtils.get(
99 | * | dataStore,
100 | * | market
101 | | );
102 | * | address tokenIn = isCollateralToIndex
103 | * | ? marketProps.shortToken
104 | * | : marketProps.indexToken;
105 | |
106 | * | address tokenOut = isCollateralToIndex
107 | * | ? marketProps.indexToken
108 | * | : marketProps.shortToken;
109 | |
110 | * | bytes[] memory exchangesData = new bytes[](2);
111 | |
112 | * | exchangesData[0] = abi.encode(isLong ? type(uint256).max : 5); //long has infinite price, shorts arbitrary small
113 | |
114 | * | if (includeSwap) {
115 | * | exchangesData[1] = constructSwapCalldata(
116 | * | tokenIn,
117 | * | tokenOut,
118 | * | amount,
119 | * | 1,
120 | * | vault
121 | | );
122 | | }
123 | |
124 | * | return exchangesData;
125 | | }
126 | |
127 | | // Wrapper function to execute the swap
128 | * | function executeSwap(
129 | | address vault,
130 | | address market,
131 | | uint leverage,
132 | | uint priceSeed,
133 | | bytes[] memory exchangesData
134 | * | ) internal {
135 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices(
136 | * | market,
137 | * | priceSeed
138 | | );
139 | |
140 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData();
141 | |
142 | * | vm.prank(gammaKeeper);
143 | * | try
144 | * | PerpetualVaultLens(vault).run(
145 | * | true, // isOpen (any)
146 | * | true, // isLong (any)
147 | * | leverage * 1e4, // leverage is 1
148 | * | convertedPrices,
149 | * | exchangesData
150 | | )
151 | * | {
152 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault)
153 | | .swapProgressData();
154 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
155 | * | fl.t(
156 | * | swappedBefore == swappedAfter,
157 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey"
158 | | );
159 | | }
160 | | } catch {}
161 | | }
162 | |
163 | | // Main function
164 | *r | function SwapOrder(
165 | | bool bothExchanges,
166 | | bool onlyParaswap,
167 | | uint8 seed,
168 | | uint priceSeed,
169 | | uint amount
170 | * | ) public {
171 | * | bytes[] memory exchangesData;
172 | * | (
173 | * | address vault,
174 | * | uint leverage,
175 | * | address market,
176 | * | address gmxUtils
177 | * | ) = _gamma_getVault(seed);
178 | |
179 | *r | require(
180 | * | PerpetualVaultLens(vault).checkForCleanStart(),
181 | | "Previous call was not executed"
182 | | );
183 | * | bool isCollateralToIndex = priceSeed % 2 == 1;
184 | |
185 | * | bothExchanges = false; //NOTE: PARASWAP EXCLUDED
186 | * | onlyParaswap = false;
187 | |
188 | * | if (bothExchanges) {
189 | | exchangesData = generateBothExchangesCalldata(
190 | | seed,
191 | | isCollateralToIndex,
192 | | priceSeed,
193 | | amount
194 | | );
195 | | } else {
196 | * | exchangesData = generateSingleExchangeCalldata(
197 | * | onlyParaswap,
198 | * | seed,
199 | * | isCollateralToIndex,
200 | * | amount
201 | | );
202 | | }
203 | |
204 | * | executeSwap(vault, market, leverage, priceSeed, exchangesData);
205 | | }
206 | *r | function IncreaseOrder(uint8 seed, uint priceSeed, bool isLong) public {
207 | * | (
208 | * | address vault,
209 | * | uint leverage,
210 | * | address market,
211 | * | address gmxUtils
212 | * | ) = _gamma_getVault(seed);
213 | |
214 | * | IERC20 index = IERC20(PerpetualVault(vault).indexToken());
215 | |
216 | *r | require(
217 | * | PerpetualVaultLens(vault).checkForCleanStart(),
218 | | "Previous call was not executed"
219 | | );
220 | |
221 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData();
222 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices(
223 | * | market,
224 | * | priceSeed
225 | | );
226 | |
227 | * | bytes[] memory data;
228 | * | if (leverage == 1) {
229 | * | bool bothExchanges = false; //NOTE: PARASWAP EXCLUDED
230 | * | bool onlyParaswap = false;
231 | |
232 | * | if (bothExchanges) {
233 | | data = generateBothExchangesCalldata(
234 | | seed,
235 | | true, //isCollateralToIndex
236 | | priceSeed,
237 | | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault)
238 | | );
239 | | } else {
240 | * | data = generateSingleExchangeCalldata(
241 | * | onlyParaswap,
242 | * | seed,
243 | * | true, //isCollateralToIndex
244 | * | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault)
245 | | );
246 | | }
247 | | } else {
248 | * | data = generateAcceptablePriceExchangeCalldata(
249 | * | seed % 2 == 0 ? true : false, //includeSwap rand
250 | * | seed,
251 | * | true, //isCollateralToIndex
252 | * | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault),
253 | * | isLong
254 | | );
255 | | }
256 | |
257 | * | vm.prank(gammaKeeper);
258 | * | try
259 | * | PerpetualVaultLens(vault).run(
260 | * | true, //isOpen
261 | * | isLong, //isLong
262 | * | leverage * 1e4, //leverage is 1,2,3
263 | * | convertedPrices, // MarketPrices memory prices
264 | * | data
265 | | )
266 | * | {
267 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault)
268 | | .swapProgressData();
269 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
270 | * | fl.t(
271 | * | swappedBefore == swappedAfter,
272 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey"
273 | | );
274 | | }
275 | | } catch {
276 | *r | require(false, "Increase Order Run call failed");
277 | | }
278 | | }
279 | |
280 | * | function DecreasePosition(uint8 seed, uint priceSeed, bool isLong) public {
281 | * | (
282 | * | address vault,
283 | * | uint leverage,
284 | * | address market,
285 | * | address gmxUtils
286 | * | ) = _gamma_getVault(seed);
287 | |
288 | * | IERC20 index = IERC20(PerpetualVault(vault).indexToken());
289 | |
290 | *r | require(
291 | * | PerpetualVaultLens(vault).checkForCleanStart(),
292 | | "Previous call was not executed"
293 | | );
294 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices(
295 | * | market,
296 | * | priceSeed
297 | | );
298 | |
299 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData();
300 | |
301 | * | bytes[] memory data;
302 | * | if (leverage == 1) {
303 | * | bool bothExchanges = false; //NOTE: PARASWAP EXCLUDED
304 | * | bool onlyParaswap = false;
305 | |
306 | * | if (bothExchanges) {
307 | | data = generateBothExchangesCalldata(
308 | | seed,
309 | | false, //isCollateralToIndex
310 | | priceSeed,
311 | | isLong ? index.balanceOf(vault) : USDC.balanceOf(vault)
312 | | ); //priceSeed is amount seed
313 | | } else {
314 | * | data = generateSingleExchangeCalldata(
315 | * | onlyParaswap,
316 | * | seed,
317 | * | false, //isCollateralToIndex
318 | * | isLong ? index.balanceOf(vault) : USDC.balanceOf(vault)
319 | | );
320 | | }
321 | | } else {
322 | * | data = new bytes[](2);
323 | |
324 | * | data[0] = abi.encode(isLong ? 5 : type(uint256).max); // inverse when decreasing
325 | | }
326 | * | vm.prank(gammaKeeper);
327 | |
328 | * | try
329 | * | PerpetualVaultLens(vault).run(
330 | * | false, //isOpen
331 | * | isLong, //isLong
332 | * | leverage * 1e4, //any leverage
333 | * | convertedPrices, // MarketPrices memory prices
334 | * | data
335 | | )
336 | * | {
337 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault)
338 | | .swapProgressData();
339 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
340 | * | fl.t(
341 | * | swappedBefore == swappedAfter,
342 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey"
343 | | );
344 | | }
345 | | } catch {
346 | *r | require(false, "DecreasePosition Run call failed");
347 | | }
348 | | }
349 | |
350 | | struct NextActionPerpsCache {
351 | | IERC20 index;
352 | | address vault;
353 | | uint leverage;
354 | | address market;
355 | | address gmxUtils;
356 | | uint256 swappedBefore;
357 | | uint256 swappedAfter;
358 | | bytes[] data;
359 | | bool bothExchanges;
360 | | bool onlyParaswap;
361 | | bool isCollateralToIndex;
362 | | PerpetualVault.FLOW currentFlow;
363 | | MarketPrices convertedPrices;
364 | | }
365 | |
366 | * | function NextActionPerps(uint8 seed, uint priceSeed) public {
367 | * | NextActionPerpsCache memory cache;
368 | |
369 | * | (
370 | * | cache.vault,
371 | * | cache.leverage,
372 | * | cache.market,
373 | * | cache.gmxUtils
374 | * | ) = _gamma_getVault(seed);
375 | |
376 | * | cache.index = IERC20(PerpetualVault(cache.vault).indexToken());
377 | |
378 | * | (, cache.swappedBefore, ) = PerpetualVault(cache.vault)
379 | | .swapProgressData();
380 | |
381 | * | if (!isNextNoAction(cache.vault)) {
382 | * | if (!isNextFinalize(cache.vault) && !isNextSettle(cache.vault)) {
383 | * | if (isNextWithdraw(cache.vault)) {
384 | * | cache.data = generateAcceptablePriceExchangeCalldata(
385 | * | cache.index.balanceOf(cache.vault) > 0,
386 | * | seed,
387 | * | false, //isCollateralToIndex, false, weth => usdc
388 | * | cache.index.balanceOf(cache.vault),
389 | * | false //short
390 | | );
391 | * | } else if (cache.leverage == 1) {
392 | * | if (isNextSwap(cache.vault)) {
393 | * | cache.data = generateSingleExchangeCalldata(
394 | * | false, // onlyParaswap, doing gmx
395 | * | seed,
396 | * | false, //isCollateralToIndex, hardcoded
397 | * | cache.index.balanceOf(cache.vault)
398 | | );
399 | * | } else if (checkNextAction(cache.vault)) {
400 | | //isLong
401 | |
402 | * | cache.bothExchanges = false; //NOTE: PARASWAP EXCLUDED
403 | * | cache.onlyParaswap = false;
404 | |
405 | * | cache.isCollateralToIndex = priceSeed % 3 == 0
406 | * | ? false
407 | * | : true;
408 | * | if (cache.bothExchanges) {
409 | | cache.data = generateBothExchangesCalldata(
410 | | seed,
411 | | cache.isCollateralToIndex,
412 | | priceSeed,
413 | | getPositionCollateral(cache.vault)
414 | | );
415 | | } else {
416 | * | cache.data = generateSingleExchangeCalldata(
417 | * | cache.onlyParaswap,
418 | * | seed,
419 | * | cache.isCollateralToIndex,
420 | * | getPositionCollateral(cache.vault)
421 | | );
422 | | }
423 | |
424 | * | cache.currentFlow = PerpetualVault(cache.vault).flow();
425 | |
426 | * | if (cache.currentFlow == PerpetualVault.FLOW.DEPOSIT) {
427 | * | cache.data = generateSingleExchangeCalldata(
428 | * | false, // onlyParaswap, doing gmx
429 | * | seed,
430 | * | true, //isCollateralToIndex, hardcoded
431 | * | USDC.balanceOf(cache.vault)
432 | | );
433 | | }
434 | | } else {
435 | * | cache.data = generateAcceptablePriceExchangeCalldata(
436 | * | cache.index.balanceOf(cache.vault) > 0,
437 | * | seed,
438 | * | false, //isCollateralToIndex weth => usdc
439 | * | cache.index.balanceOf(cache.vault),
440 | * | false //short
441 | | );
442 | | }
443 | | } else {
444 | * | cache.data = generateAcceptablePriceExchangeCalldata(
445 | * | cache.index.balanceOf(cache.vault) > 0, //includeSwap rand
446 | * | seed,
447 | * | false, //isCollateralToIndex WETH => USDC
448 | * | cache.index.balanceOf(cache.vault),
449 | * | checkNextAction(cache.vault)
450 | | );
451 | | }
452 | | } else {
453 | * | if (
454 | * | isNextFinalize(cache.vault) &&
455 | * | cache.index.balanceOf(address(cache.vault)) > 0
456 | | ) {
457 | * | cache.bothExchanges = true; //NOTE: PARASWAP INCLUDED
458 | * | cache.onlyParaswap = false;
459 | |
460 | * | cache.isCollateralToIndex = false; //hardcoded in a PerpetualVault _runSwap(metadata, false);
461 | |
462 | * | if (cache.bothExchanges) {
463 | * | cache.data = generateBothExchangesCalldata(
464 | * | seed,
465 | * | cache.isCollateralToIndex,
466 | * | priceSeed,
467 | * | cache.index.balanceOf(address(cache.vault))
468 | | );
469 | | } else {
470 | | cache.data = generateSingleExchangeCalldata(
471 | | cache.onlyParaswap,
472 | | seed,
473 | | cache.isCollateralToIndex,
474 | | cache.index.balanceOf(address(cache.vault))
475 | | );
476 | | }
477 | | }
478 | | }
479 | | } else {
480 | | //NO ACTION branch, will trigger compound
481 | * | if (cache.leverage == 1) {
482 | * | cache.bothExchanges = false; //NOTE: PARASWAP INCLUDED
483 | * | cache.onlyParaswap = false;
484 | |
485 | * | cache.isCollateralToIndex = true; //hardcoded in a PerpetualVault _runSwap(metadata, true);
486 | |
487 | * | if (cache.bothExchanges) {
488 | | cache.data = generateBothExchangesCalldata(
489 | | seed,
490 | | cache.isCollateralToIndex,
491 | | priceSeed,
492 | | USDC.balanceOf(address(cache.vault))
493 | | );
494 | | } else {
495 | * | cache.data = generateSingleExchangeCalldata(
496 | * | cache.onlyParaswap,
497 | * | seed,
498 | * | cache.isCollateralToIndex,
499 | * | USDC.balanceOf(address(cache.vault))
500 | | );
501 | | }
502 | | } else {
503 | * | cache.data = generateAcceptablePriceExchangeCalldata(
504 | * | false, //we need just an acceptable price in this case
505 | * | seed,
506 | * | false,
507 | * | 0,
508 | * | false
509 | | );
510 | | }
511 | | }
512 | * | cache.convertedPrices = getConvertedMarketPrices(
513 | * | cache.market,
514 | * | priceSeed
515 | | );
516 | * | vm.prank(gammaKeeper);
517 | * | try
518 | * | PerpetualVaultLens(cache.vault).runNextAction(
519 | * | cache.convertedPrices,
520 | * | cache.data
521 | | )
522 | | {
523 | * | (, cache.swappedAfter, ) = PerpetualVault(cache.vault)
524 | | .swapProgressData();
525 | * | if (PerpetualVault(cache.vault).curPositionKey() != bytes32(0)) {
526 | * | fl.t(
527 | * | cache.swappedBefore == cache.swappedAfter,
528 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey"
529 | | );
530 | | }
531 | | } catch {
532 | *r | require(false, "Next action run call failed");
533 | | }
534 | | }
535 | |
536 | * | function ExecuteOrder(
537 | | uint8 seed,
538 | | uint priceSeed,
539 | | bool isAtomicExec
540 | * | ) public {
541 | * | (address vault, , , address gmxUtils) = _gamma_getVault(seed);
542 | |
543 | * | (bytes32 requestKey, , , ) = GmxUtils(payable(gmxUtils)).queue();
544 | |
545 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
546 | |
547 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
548 | * | tokenPrices.tokens,
549 | * | tokenPrices.maxPrices,
550 | * | tokenPrices.minPrices
551 | | );
552 | |
553 | * | if (requestKey != 0) {
554 | * | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow();
555 | * | (
556 | * | PerpetualVault.NextActionSelector currentAction,
557 | |
558 | * | ) = PerpetualVault(vault).nextAction();
559 | * | _gammaBefore();
560 | |
561 | * | if (currentFlow == PerpetualVault.FLOW.DEPOSIT) {
562 | * | _executeOrder(requestKey, oracleParams);
563 | * | _gammaAfter();
564 | |
565 | * | _invariant_GAMMA_02(vault);
566 | * | _invariant_GAMMA_08(vault, priceSeed);
567 | | }
568 | * | if (currentFlow == PerpetualVault.FLOW.SIGNAL_CHANGE) {
569 | * | _executeOrder(requestKey, oracleParams);
570 | * | _gammaAfter();
571 | |
572 | * | _invariant_GAMMA_02(vault);
573 | * | _invariant_GAMMA_03(vault);
574 | | }
575 | * | if (currentFlow == PerpetualVault.FLOW.WITHDRAW) {
576 | * | _executeOrder(requestKey, oracleParams);
577 | * | _gammaAfter();
578 | * | _invariant_GAMMA_02(vault);
579 | |
580 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
581 | * | fl.t(
582 | * | currentFlow == PerpetualVault.FLOW.WITHDRAW,
583 | | "GAMMA-11: If withdraw function is called on a open GMX position, callback should always hit the settle case in the afterOrderExecution and afterOrderCancellation function."
584 | | );
585 | | }
586 | | }
587 | * | if (currentFlow == PerpetualVault.FLOW.COMPOUND) {
588 | * | _executeOrder(requestKey, oracleParams);
589 | * | _gammaAfter();
590 | * | _invariant_GAMMA_02(vault);
591 | | }
592 | * | if (currentFlow == PerpetualVault.FLOW.NONE) {
593 | * | _executeOrder(requestKey, oracleParams);
594 | * | _gammaAfter();
595 | |
596 | * | _invariant_GAMMA_03(vault);
597 | | }
598 | | } else {
599 | *r | require(false, "Execute order failed");
600 | | }
601 | |
602 | * | logNextAction(vault);
603 | | }
604 | * | function _executeOrder(
605 | | bytes32 requestKey,
606 | | OracleUtils.SetPricesParams memory oracleParams
607 | * | ) internal {
608 | * | bytes memory callData_ExecuteOrder = abi.encodeWithSelector(
609 | * | orderHandler.executeOrder.selector,
610 | * | requestKey,
611 | * | oracleParams
612 | | );
613 | * | vm.prank(DEPLOYER);
614 | |
615 | * | (
616 | * | bool success_ExecuteOrder,
617 | * | bytes memory returnData_ExecuteOrder
618 | * | ) = address(orderHandler).call{gas: 30_000_000}(callData_ExecuteOrder);
619 | | }
620 | |
621 | *r | function CancelOrder(uint8 seed, uint priceSeed, bool isAtomicExec) public {
622 | * | (address vault, , , address gmxUtils) = _gamma_getVault(seed);
623 | |
624 | * | (bytes32 requestKey, , , ) = GmxUtils(payable(gmxUtils)).queue();
625 | |
626 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
627 | |
628 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
629 | * | tokenPrices.tokens,
630 | * | tokenPrices.maxPrices,
631 | * | tokenPrices.minPrices
632 | | );
633 | |
634 | * | if (requestKey != 0) {
635 | * | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow();
636 | * | (
637 | * | PerpetualVault.NextActionSelector currentAction,
638 | |
639 | * | ) = PerpetualVault(vault).nextAction();
640 | * | _gammaBefore();
641 | |
642 | * | bytes memory callData_CancelOrder = abi.encodeWithSelector(
643 | * | orderHandler.cancelOrder.selector,
644 | * | requestKey
645 | | );
646 | * | vm.prank(DEPLOYER);
647 | |
648 | * | (
649 | * | bool success_CancelOrder,
650 | * | bytes memory returnData_CancelOrder
651 | * | ) = address(orderHandler).call{gas: 30_000_000}(
652 | * | callData_CancelOrder
653 | | );
654 | |
655 | * | if (success_CancelOrder) {
656 | * | if (currentFlow == PerpetualVault.FLOW.WITHDRAW) {
657 | | fl.t(
658 | | currentAction ==
659 | | PerpetualVault.NextActionSelector.SETTLE_ACTION,
660 | | "GAMMA-11: If withdraw function is called on a open GMX position, callback should always hit the settle case in the afterOrderExecution and afterOrderCancellation function."
661 | | );
662 | | }
663 | | }
664 | | }
665 | | }
666 | | }
667 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/PositionSpeedup.sol
1 | | pragma solidity ^0.8.0;
2 | |
3 | | import "./PositionSetup.sol";
4 | |
5 | | contract PositionSpeedup is PositionSetup {}
6 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/shiftSetup/ShiftSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "../depositSetup/DepositSpeedup.sol";
5 | |
6 | | contract ShiftSetup is DepositSpeedup {}
7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/shiftSetup/ShiftSpeedup.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "./ShiftSetup.sol";
5 | |
6 | | contract ShiftSpeedup is ShiftSetup {}
7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/withdrawSetup/WithdrawSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./../PropertiesSetup.sol";
6 | | import "../../../contracts/withdrawal/WithdrawalUtils.sol";
7 | |
8 | | contract WithdrawSetup is PropertiesSetup {
9 | | WithdrawalCreated[] internal withdrawalCreatedArray;
10 | |
11 | | /**
12 | | //
13 | | // GAMMA withdrawals
14 | | //
15 | | */
16 | |
17 | *r | function GammaWithdraw(
18 | | uint8 seed,
19 | | uint8 userSeed,
20 | | uint priceSeed
21 | * | ) public returns (bool success, uint depositAmount, uint timestamp) {
22 | * | DepositInfo memory deposit;
23 | |
24 | * | (withdrawalAssertionInputs.vault, , , ) = _gamma_getVault(seed);
25 | *r | require(
26 | * | PerpetualVaultLens(withdrawalAssertionInputs.vault)
27 | | .checkForCleanStart(),
28 | | "Previous call was not executed"
29 | | );
30 | * | withdrawalAssertionInputs.user = _getRandomUser(userSeed);
31 | * | withdrawalAssertionInputs.depositId = _getRandomDepositId(
32 | * | seed,
33 | * | withdrawalAssertionInputs.user,
34 | * | withdrawalAssertionInputs.vault
35 | | );
36 | * | uint256 executionFee = PerpetualVault(withdrawalAssertionInputs.vault)
37 | * | .getExecutionGasLimit(true);
38 | |
39 | * | (depositAmount, , , , timestamp, ) = PerpetualVault(
40 | * | withdrawalAssertionInputs.vault
41 | * | ).depositInfo(withdrawalAssertionInputs.depositId);
42 | |
43 | * | vm.warp(
44 | * | timestamp +
45 | * | PerpetualVault(withdrawalAssertionInputs.vault).lockTime() +
46 | * | 1
47 | | ); //to satisfy < comparison
48 | | //prank inside:)
49 | * | bytes memory returnData;
50 | * | (success, returnData) = _gamma_WithdrawCall(
51 | * | withdrawalAssertionInputs.user,
52 | * | withdrawalAssertionInputs.vault,
53 | * | withdrawalAssertionInputs.depositId,
54 | * | executionFee
55 | | );
56 | |
57 | * | if (returnData.length > 0) {
58 | * | fl.log(
59 | | "Gamma withdraw return data",
60 | * | abi.decode(returnData, (string))
61 | | );
62 | | }
63 | | }
64 | |
65 | | /**
66 | | //
67 | | // GMX withdrawals
68 | | //
69 | | */
70 | |
71 | | struct WithdrawalCache {
72 | | address[] longSwapPath;
73 | | address[] shortSwapPath;
74 | | address market;
75 | | address user;
76 | | }
77 | |
78 | *r | function WithdrawLP(
79 | | uint8 userIndex,
80 | | uint8 marketIndex,
81 | | uint withdrawalAmountSeed,
82 | | uint priceSeed,
83 | | uint8 swapPathSeed,
84 | | uint executionFee,
85 | | bool isAtomic
86 | | ) public {
87 | * | WithdrawalCache memory cache;
88 | * | executionFee = 0; //In withdrawals, we are not performing an execution fee check because of the implemented method of state change verification
89 | |
90 | * | if (!SWAPS_ENABLED) {
91 | * | swapPathSeed = 7;
92 | | }
93 | |
94 | * | cache.longSwapPath = _getSwapPath(swapPathSeed);
95 | * | cache.shortSwapPath = _getSwapPath(
96 | * | SWAPS_ENABLED ? swapPathSeed / 3 : 7
97 | | ); //another path
98 | |
99 | * | cache.market = _getMarketAddress(marketIndex);
100 | * | Market.Props memory marketProps = MarketStoreUtils.get(
101 | * | dataStore,
102 | * | cache.market
103 | | );
104 | |
105 | * | cache.user = _getRandomUser(userIndex);
106 | * | uint userBalance = ERC20(cache.market).balanceOf(cache.user);
107 | |
108 | * | WithdrawalUtils.CreateWithdrawalParams
109 | * | memory withdrawalParams = _setCreateWithdrawalParams(
110 | * | cache.user,
111 | * | address(0),
112 | * | address(0),
113 | * | cache.market,
114 | * | cache.longSwapPath, // longTokenSwapPath
115 | * | cache.shortSwapPath, // shortTokenSwapPath
116 | * | 1, //min long token amount
117 | * | 1, //min short token amount
118 | * | false, //unwrap
119 | * | executionFee,
120 | * | 200 * 1000
121 | | );
122 | |
123 | * | WithdrawalState memory stateBefore = _snapWithdrawalState(
124 | * | cache.user,
125 | * | cache.market
126 | | );
127 | |
128 | | //Idea is to have bigger value than balance, but not as huge to create lots of empty fuzz runs
129 | * | uint amountToWithdraw = clampBetween(
130 | * | withdrawalAmountSeed,
131 | * | 0,
132 | * | userBalance * 2
133 | | );
134 | |
135 | * | (
136 | * | stateBefore.simulateLongTokenAmountWithdrawal,
137 | * | stateBefore.simulateShortTokenAmountWithdrawal
138 | * | ) = _simulateWithdrawalAmount(
139 | * | marketProps,
140 | * | amountToWithdraw,
141 | * | priceSeed,
142 | * | isAtomic
143 | | );
144 | |
145 | * | WithdrawalCreated memory withdrawalCreated = _withdraw(
146 | * | amountToWithdraw,
147 | * | withdrawalParams
148 | | );
149 | |
150 | | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal(
151 | | dataStore,
152 | | withdrawalCreated.withdrawalKey
153 | | );
154 | |
155 | | if (isAtomic) {
156 | | ExecuteAtomicWithdawal(
157 | | withdrawalParams,
158 | | priceSeed,
159 | | cache.user,
160 | | amountToWithdraw
161 | | );
162 | | _checkExecuteAtomicWithdrawalCoverage(withdrawalProps);
163 | | } else {
164 | | ExecuteWithdrawal(priceSeed, true);
165 | | _checkExecuteWithdrawalCoverage(withdrawalProps);
166 | | }
167 | |
168 | | WithdrawalState memory stateAfter = _snapWithdrawalState(
169 | | cache.user,
170 | | cache.market
171 | | );
172 | |
173 | | require(
174 | | stateBefore.userBalance > stateAfter.userBalance,
175 | | "Withdrawal state was not changed"
176 | | );
177 | |
178 | | invariantWithdrawnTokensMatchSimulatedAmounts(
179 | | stateBefore,
180 | | stateAfter,
181 | | withdrawalCreated
182 | | );
183 | | invariantMarketTokenSupplyDecreases(stateBefore, stateAfter);
184 | | }
185 | |
186 | *r | function CreateWithdrawal(
187 | | uint8 userIndex,
188 | | uint8 marketIndex,
189 | | uint withdrawalAmountSeed
190 | * | ) public {
191 | * | address market = _getMarketAddress(marketIndex);
192 | * | Market.Props memory marketProps = MarketStoreUtils.get(
193 | * | dataStore,
194 | * | market
195 | | );
196 | |
197 | * | address user = _getRandomUser(userIndex);
198 | * | uint userBalance = ERC20(market).balanceOf(user); //NOTE: not checking if balance != 0, putting it into assertions
199 | |
200 | * | uint amountToWithdraw = clampBetween(
201 | * | withdrawalAmountSeed,
202 | * | 0,
203 | * | userBalance * 2
204 | | );
205 | |
206 | * | WithdrawalUtils.CreateWithdrawalParams
207 | * | memory withdrawalParams = _setCreateWithdrawalParams(
208 | * | user,
209 | * | address(0),
210 | * | address(0),
211 | * | market,
212 | * | _getSwapPath(7), //currently empty to check exact output token amounts, // longTokenSwapPath
213 | * | _getSwapPath(7), //currently empty to check exact output token amounts,
214 | * | 1, //min long token amount
215 | * | 1, //min short token amount
216 | * | false, //unwrap
217 | * | 0,
218 | * | 200 * 1000
219 | | );
220 | |
221 | * | WithdrawalCreated memory withdrawalCreated = _withdraw(
222 | * | amountToWithdraw,
223 | * | withdrawalParams
224 | | );
225 | |
226 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal(
227 | * | dataStore,
228 | * | withdrawalCreated.withdrawalKey
229 | | );
230 | * | _checkCreateWithdrawalCoverage(withdrawalProps);
231 | | }
232 | |
233 | * | function _withdraw(
234 | | uint amount,
235 | | WithdrawalUtils.CreateWithdrawalParams memory withdrawalParams
236 | * | ) internal returns (WithdrawalCreated memory withdrawalCreated) {
237 | * | address user = withdrawalParams.receiver;
238 | |
239 | * | _mintAndSendTokensTo(
240 | * | user,
241 | * | address(withdrawalVault),
242 | * | withdrawalParams.executionFee,
243 | * | 0,
244 | * | address(WETH),
245 | * | address(0),
246 | * | 0,
247 | * | true
248 | | );
249 | *r | require(
250 | * | ERC20(withdrawalParams.market).balanceOf(user) > 0,
251 | | "Withdrawal: user has no market tokens"
252 | | );
253 | |
254 | * | vm.prank(user);
255 | *r | ERC20(withdrawalParams.market).transfer(
256 | * | address(withdrawalVault),
257 | * | amount
258 | | );
259 | |
260 | * | bytes memory callData_CreateWithdrawal = abi.encodeWithSelector(
261 | * | exchangeRouter.createWithdrawal.selector,
262 | * | withdrawalParams
263 | | );
264 | * | vm.prank(user);
265 | |
266 | * | (
267 | * | bool success_CreateWithdrawal,
268 | * | bytes memory returnData_CreateWithdrawal
269 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(
270 | * | callData_CreateWithdrawal
271 | | );
272 | |
273 | * | bytes32 withdrawalKey;
274 | * | if (!success_CreateWithdrawal) {
275 | * | invariantDoesNotSilentRevert(returnData_CreateWithdrawal);
276 | | } else {
277 | * | withdrawalKey = abi.decode(returnData_CreateWithdrawal, (bytes32));
278 | | }
279 | |
280 | * | withdrawalCreated.withdrawalParams = withdrawalParams;
281 | * | withdrawalCreated.amount = amount;
282 | * | withdrawalCreated.withdrawalKey = withdrawalKey;
283 | * | withdrawalCreatedArray.push(withdrawalCreated);
284 | | }
285 | |
286 | *r | function ExecuteAtomicWithdawal(
287 | | WithdrawalUtils.CreateWithdrawalParams memory withdrawalParams,
288 | | uint priceSeed,
289 | | address user,
290 | | uint amountToWithdraw
291 | | ) public {
292 | * | Market.Props memory marketProps = MarketStoreUtils.get(
293 | * | dataStore,
294 | * | withdrawalParams.market
295 | | );
296 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
297 | |
298 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
299 | * | tokenPrices.tokens,
300 | * | tokenPrices.maxPrices,
301 | * | tokenPrices.minPrices
302 | | );
303 | |
304 | * | _mintAndSendTokensTo(
305 | * | user,
306 | * | address(withdrawalVault),
307 | * | withdrawalParams.executionFee,
308 | * | 0,
309 | * | address(WETH),
310 | * | address(0),
311 | * | 0,
312 | * | true
313 | | );
314 | * | uint longTokenBalanceBefore = ERC20(marketProps.longToken).balanceOf(
315 | * | withdrawalParams.market
316 | | );
317 | * | uint shortTokenBalanceBefore = ERC20(marketProps.shortToken).balanceOf(
318 | * | withdrawalParams.market
319 | | );
320 | |
321 | * | require(
322 | * | ERC20(withdrawalParams.market).balanceOf(user) > 0,
323 | | "AtomicWithdrawal: user has no market tokens"
324 | | );
325 | |
326 | * | vm.prank(user);
327 | * | ERC20(withdrawalParams.market).transfer(
328 | * | address(withdrawalVault),
329 | * | amountToWithdraw
330 | | );
331 | |
332 | * | bytes memory callData_ExecuteAtomicWithdrawal = abi.encodeWithSelector(
333 | * | exchangeRouter.executeAtomicWithdrawal.selector,
334 | * | withdrawalParams,
335 | * | oracleParams
336 | | );
337 | |
338 | * | vm.prank(user);
339 | |
340 | * | (
341 | * | bool success_ExecuteAtomicWithdrawal,
342 | * | bytes memory returnData_ExecuteAtomicWithdrawal
343 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(
344 | * | callData_ExecuteAtomicWithdrawal
345 | | );
346 | |
347 | * | if (!success_ExecuteAtomicWithdrawal) {
348 | * | invariantDoesNotSilentRevert(returnData_ExecuteAtomicWithdrawal);
349 | | }
350 | |
351 | | require(longTokenBalanceBefore != 0 || shortTokenBalanceBefore != 0);
352 | | require(
353 | | longTokenBalanceBefore != 0
354 | | ? longTokenBalanceBefore >
355 | | ERC20(marketProps.longToken).balanceOf(
356 | | withdrawalParams.market
357 | | )
358 | | : shortTokenBalanceBefore >
359 | | ERC20(marketProps.shortToken).balanceOf(
360 | | withdrawalParams.market
361 | | )
362 | | ); //checking if market address has less tokens after execution == some withdrawal succeed
363 | | }
364 | |
365 | *r | function ExecuteWithdrawal(uint priceSeed, bool isAtomicExec) public {
366 | *r | require(
367 | * | withdrawalCreatedArray.length > 0,
368 | | "No withdrawals available to execute"
369 | | );
370 | |
371 | * | uint256 randomIndex = isAtomicExec
372 | * | ? withdrawalCreatedArray.length - 1
373 | * | : clampBetween(priceSeed, 0, withdrawalCreatedArray.length - 1);
374 | |
375 | * | WithdrawalCreated memory withdrawalToExecute = withdrawalCreatedArray[
376 | * | randomIndex
377 | | ];
378 | * | Market.Props memory marketProps = MarketStoreUtils.get(
379 | * | dataStore,
380 | * | withdrawalToExecute.withdrawalParams.market
381 | | );
382 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed);
383 | |
384 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices(
385 | * | tokenPrices.tokens,
386 | * | tokenPrices.maxPrices,
387 | * | tokenPrices.minPrices
388 | | );
389 | |
390 | * | uint longTokenBalanceBefore = ERC20(marketProps.longToken).balanceOf(
391 | * | withdrawalToExecute.withdrawalParams.market
392 | | );
393 | * | uint shortTokenBalanceBefore = ERC20(marketProps.shortToken).balanceOf(
394 | * | withdrawalToExecute.withdrawalParams.market
395 | | );
396 | |
397 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal(
398 | * | dataStore,
399 | * | withdrawalToExecute.withdrawalKey
400 | | );
401 | |
402 | * | uint userLongTokenBalanceBefore = ERC20(marketProps.longToken)
403 | * | .balanceOf(withdrawalProps.addresses.account);
404 | * | uint userShortTokenBalanceBefore = ERC20(marketProps.shortToken)
405 | * | .balanceOf(withdrawalProps.addresses.account);
406 | |
407 | * | _executeWithdrawal(
408 | * | withdrawalToExecute.withdrawalKey,
409 | * | oracleParams,
410 | * | withdrawalToExecute.withdrawalParams.executionFee,
411 | * | isAtomicExec
412 | | );
413 | |
414 | * | require(longTokenBalanceBefore != 0 || shortTokenBalanceBefore != 0);
415 | * | require(
416 | * | longTokenBalanceBefore != 0
417 | * | ? longTokenBalanceBefore >
418 | * | ERC20(marketProps.longToken).balanceOf(
419 | * | withdrawalToExecute.withdrawalParams.market
420 | | )
421 | | : shortTokenBalanceBefore >
422 | | ERC20(marketProps.shortToken).balanceOf(
423 | | withdrawalToExecute.withdrawalParams.market
424 | | )
425 | | ); //checking if market address has less tokens after execution == some withdrawal succeed
426 | |
427 | * | _checkExecuteAtomicWithdrawalCoverage(withdrawalProps);
428 | |
429 | * | uint userLongTokenBalanceAfter = ERC20(marketProps.longToken).balanceOf(
430 | * | withdrawalProps.addresses.account
431 | | );
432 | * | uint userShortTokenBalanceAfter = ERC20(marketProps.shortToken)
433 | * | .balanceOf(withdrawalProps.addresses.account);
434 | |
435 | * | fl.gt(
436 | * | userLongTokenBalanceAfter,
437 | * | userLongTokenBalanceBefore,
438 | | "GAMMA-14: if user withdraws they will get non zero amount in return"
439 | | );
440 | |
441 | * | withdrawalCreatedArray[randomIndex] = withdrawalCreatedArray[
442 | * | withdrawalCreatedArray.length - 1
443 | | ];
444 | * | withdrawalCreatedArray.pop();
445 | | }
446 | *r | function CancelWithdrawal(
447 | | uint seed,
448 | | bool isAtomicExec
449 | | )
450 | | public
451 | | returns (
452 | * | WithdrawalState memory _before,
453 | * | WithdrawalState memory _after,
454 | * | WithdrawalCreated memory withdrawalToCancel
455 | | )
456 | * | {
457 | *r | require(
458 | * | withdrawalCreatedArray.length > 0,
459 | | "No withdrawals available to execute"
460 | | );
461 | |
462 | * | uint256 randomIndex = isAtomicExec
463 | * | ? withdrawalCreatedArray.length - 1
464 | * | : clampBetween(seed, 0, withdrawalCreatedArray.length - 1);
465 | |
466 | * | withdrawalToCancel = withdrawalCreatedArray[randomIndex];
467 | |
468 | * | _before = _snapWithdrawalState(
469 | * | withdrawalToCancel.withdrawalParams.receiver,
470 | * | withdrawalToCancel.withdrawalParams.market
471 | | );
472 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal(
473 | * | dataStore,
474 | * | withdrawalToCancel.withdrawalKey
475 | | );
476 | |
477 | * | bytes memory callData_CancelWithdrawal = abi.encodeWithSelector(
478 | * | exchangeRouter.cancelWithdrawal.selector,
479 | * | withdrawalToCancel.withdrawalKey
480 | | );
481 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME);
482 | |
483 | * | vm.prank(withdrawalToCancel.withdrawalParams.receiver);
484 | |
485 | * | (
486 | * | bool success_CancelWithdrawal,
487 | * | bytes memory returnData_CancelWithdrawal
488 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(
489 | * | callData_CancelWithdrawal
490 | | );
491 | |
492 | * | if (!success_CancelWithdrawal) {
493 | * | invariantDoesNotSilentRevert(returnData_CancelWithdrawal);
494 | | }
495 | |
496 | * | _after = _snapWithdrawalState(
497 | * | withdrawalToCancel.withdrawalParams.receiver,
498 | * | withdrawalToCancel.withdrawalParams.market
499 | | );
500 | |
501 | * | _checkCancelWithdrawalCoverage(withdrawalProps);
502 | | }
503 | |
504 | * | function _executeWithdrawal(
505 | | bytes32 key,
506 | | OracleUtils.SetPricesParams memory oracleParams,
507 | | uint executionFee,
508 | | bool isAtomicExec
509 | * | ) internal {
510 | * | callback.cleanETHBalance(address(0));
511 | * | uint before_callbackBalance_GEN2 = address(callback).balance;
512 | |
513 | * | vm.prank(DEPLOYER);
514 | *r | withdrawalHandler.executeWithdrawal{gas: 30_000_000}(key, oracleParams);
515 | | if (isAtomicExec) {
516 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version
517 | | // address(0),
518 | | // before_callbackBalance_GEN2,
519 | | // address(callback).balance,
520 | | // executionFee
521 | | // );
522 | | }
523 | | }
524 | |
525 | * | function _simulateWithdrawalAmount(
526 | | Market.Props memory marketProps,
527 | | uint amountToWithdraw,
528 | | uint priceSeed,
529 | | bool isAtomic
530 | | )
531 | | internal
532 | | returns (
533 | * | uint simulateLongTokenAmountWithdrawal,
534 | * | uint simulateShortTokenAmountWithdrawal
535 | | )
536 | | {
537 | * | (
538 | | simulateLongTokenAmountWithdrawal,
539 | | simulateShortTokenAmountWithdrawal
540 | * | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut(
541 | * | dataStore,
542 | * | marketProps,
543 | * | _getMarketPrices(
544 | * | marketProps.marketToken,
545 | * | _setTokenPrices(priceSeed)
546 | | ),
547 | * | amountToWithdraw,
548 | * | address(0),
549 | * | isAtomic
550 | * | ? ISwapPricingUtils.SwapPricingType.Atomic
551 | * | : ISwapPricingUtils.SwapPricingType.TwoStep
552 | | );
553 | | }
554 | |
555 | * | function _setCreateWithdrawalParams(
556 | | address receiver,
557 | | address callbackContract,
558 | | address uiFeeReceiver,
559 | | address market,
560 | | address[] memory longTokenSwapPath,
561 | | address[] memory shortTokenSwapPath,
562 | | uint256 minLongTokenAmount,
563 | | uint256 minShortTokenAmount,
564 | | bool shouldUnwrapNativeToken,
565 | | uint256 executionFee,
566 | | uint256 callbackGasLimit
567 | * | ) internal pure returns (WithdrawalUtils.CreateWithdrawalParams memory) {
568 | * | WithdrawalUtils.CreateWithdrawalParams memory params = WithdrawalUtils
569 | | .CreateWithdrawalParams({
570 | * | receiver: receiver,
571 | * | callbackContract: callbackContract,
572 | * | uiFeeReceiver: uiFeeReceiver,
573 | * | market: market,
574 | * | longTokenSwapPath: longTokenSwapPath,
575 | * | shortTokenSwapPath: shortTokenSwapPath,
576 | * | minLongTokenAmount: minLongTokenAmount,
577 | * | minShortTokenAmount: minShortTokenAmount,
578 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken,
579 | * | executionFee: executionFee,
580 | * | callbackGasLimit: callbackGasLimit
581 | | });
582 | |
583 | * | return params;
584 | | }
585 | | }
586 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/withdrawSetup/WithdrawSpeedup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./WithdrawSetup.sol";
6 | |
7 | | contract WithdrawSpeedup is WithdrawSetup {
8 | *r | function CreateCancelWithdrawal(
9 | | uint8 userIndex,
10 | | uint8 marketIndex,
11 | | uint withdrawalAmountSeed
12 | * | ) public {
13 | * | CreateWithdrawal(userIndex, marketIndex, withdrawalAmountSeed);
14 | * | (
15 | * | WithdrawalState memory _before,
16 | * | WithdrawalState memory _after,
17 | * | WithdrawalCreated memory withdrawalToCancel
18 | * | ) = CancelWithdrawal(withdrawalAmountSeed, true);
19 | |
20 | * | _cancelWithdrawalAssertions(_before, _after, withdrawalToCancel);
21 | | }
22 | | }
23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/interfaces/IMockDex.sol
1 | | pragma solidity ^0.8.0;
2 | | pragma experimental ABIEncoderV2;
3 | |
4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5 | |
6 | | interface IMockDex {
7 | | /**
8 | | * @param fromToken Address of the source token
9 | | * @param fromAmount Amount of source tokens to be swapped
10 | | * @param toAmount Minimum destination token amount expected out of this swap
11 | | * @param expectedAmount Expected amount of destination tokens without slippage
12 | | * @param beneficiary Beneficiary address
13 | | * 0 then 100% will be transferred to beneficiary. Pass 10000 for 100%
14 | | * @param referrer referral id
15 | | * @param useReduxToken whether to use redux token or not
16 | | * @param path Route to be taken for this swap to take place
17 | |
18 | | */
19 | | struct SellData {
20 | | address fromToken;
21 | | uint256 fromAmount;
22 | | uint256 toAmount;
23 | | uint256 expectedAmount;
24 | | address payable beneficiary;
25 | | string referrer;
26 | | bool useReduxToken;
27 | | Path[] path;
28 | | }
29 | |
30 | | struct MegaSwapSellData {
31 | | address fromToken;
32 | | uint256 fromAmount;
33 | | uint256 toAmount;
34 | | uint256 expectedAmount;
35 | | address payable beneficiary;
36 | | string referrer;
37 | | bool useReduxToken;
38 | | MegaSwapPath[] path;
39 | | }
40 | |
41 | | struct BuyData {
42 | | address fromToken;
43 | | address toToken;
44 | | uint256 fromAmount;
45 | | uint256 toAmount;
46 | | address payable beneficiary;
47 | | string referrer;
48 | | bool useReduxToken;
49 | | BuyRoute[] route;
50 | | }
51 | |
52 | | struct Route {
53 | | address payable exchange;
54 | | address targetExchange;
55 | | uint percent;
56 | | bytes payload;
57 | | uint256 networkFee; //Network fee is associated with 0xv3 trades
58 | | }
59 | |
60 | | struct MegaSwapPath {
61 | | uint256 fromAmountPercent;
62 | | Path[] path;
63 | | }
64 | |
65 | | struct Path {
66 | | address to;
67 | | uint256 totalNetworkFee; //Network fee is associated with 0xv3 trades
68 | | Route[] routes;
69 | | }
70 | |
71 | | struct BuyRoute {
72 | | address payable exchange;
73 | | address targetExchange;
74 | | uint256 fromAmount;
75 | | uint256 toAmount;
76 | | bytes payload;
77 | | uint256 networkFee; //Network fee is associated with 0xv3 trades
78 | | }
79 | |
80 | | // function getPartnerRegistry() external view returns (address);
81 | |
82 | | // function getWhitelistAddress() external view returns (address);
83 | |
84 | | // function getFeeWallet() external view returns (address);
85 | |
86 | | // function getTokenTransferProxy() external view returns (address);
87 | |
88 | | // function getUniswapProxy() external view returns (address);
89 | |
90 | | // function getVersion() external view returns (string memory);
91 | |
92 | | /**
93 | | * @dev The function which performs the multi path swap.
94 | | */
95 | | // function multiSwap(
96 | | // SellData calldata data
97 | | // ) external payable returns (uint256);
98 | |
99 | | /**
100 | | * @dev The function which performs the single path buy.
101 | | */
102 | | // function buy(BuyData calldata data) external payable returns (uint256);
103 | |
104 | | // function swapOnUniswap(
105 | | // uint256 amountIn,
106 | | // uint256 amountOutMin,
107 | | // address[] calldata path,
108 | | // uint8 referrer
109 | | // ) external payable;
110 | |
111 | | // function buyOnUniswap(
112 | | // uint256 amountInMax,
113 | | // uint256 amountOut,
114 | | // address[] calldata path,
115 | | // uint8 referrer
116 | | // ) external payable;
117 | |
118 | | // function buyOnUniswapFork(
119 | | // address factory,
120 | | // bytes32 initCode,
121 | | // uint256 amountInMax,
122 | | // uint256 amountOut,
123 | | // address[] calldata path,
124 | | // uint8 referrer
125 | | // ) external payable;
126 | |
127 | | // function swapOnUniswapFork(
128 | | // address factory,
129 | | // bytes32 initCode,
130 | | // uint256 amountIn,
131 | | // uint256 amountOutMin,
132 | | // address[] calldata path,
133 | | // uint8 referrer
134 | | // ) external payable;
135 | |
136 | | // function simplBuy(
137 | | // address fromToken,
138 | | // address toToken,
139 | | // uint256 fromAmount,
140 | | // uint256 toAmount,
141 | | // address[] memory callees,
142 | | // bytes memory exchangeData,
143 | | // uint256[] memory startIndexes,
144 | | // uint256[] memory values,
145 | | // address payable beneficiary,
146 | | // string memory referrer,
147 | | // bool useReduxToken
148 | | // ) external payable;
149 | |
150 | | // function simpleSwap(
151 | | // address fromToken,
152 | | // address toToken,
153 | | // uint256 fromAmount,
154 | | // uint256 toAmount,
155 | | // uint256 expectedAmount,
156 | | // address[] memory callees,
157 | | // bytes memory exchangeData,
158 | | // uint256[] memory startIndexes,
159 | | // uint256[] memory values,
160 | | // address payable beneficiary,
161 | | // string memory referrer,
162 | | // bool useReduxToken
163 | | // ) external payable returns (uint256 receivedAmount);
164 | |
165 | | /**
166 | | * @dev The function which performs the mega path swap.
167 | | * @param data Data required to perform swap.
168 | | */
169 | | function megaSwap(
170 | | MegaSwapSellData memory data
171 | | ) external payable returns (uint256);
172 | | }
173 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/ADLCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../properties/BeforeAfter.sol";
6 | |
7 | | contract ADLCoverage is BeforeAfter {}
8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/DepositCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../properties/BeforeAfter.sol";
6 | |
7 | | contract DepositCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ CREATE DEPOSIT COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | * | function _checkCreateDepositCoverage(
14 | | address market,
15 | | address longToken,
16 | | address shortToken,
17 | | TokenPrices memory tokenPrices,
18 | | address user,
19 | | uint longAmount,
20 | | uint shortAmount
21 | | ) internal {
22 | * | _logMarketCoverage_CreateDeposit(market);
23 | * | _logTokenCoverage_Long_CreateDeposit(
24 | * | longToken,
25 | | "LongToken",
26 | * | _getTokenPrice(longToken, tokenPrices)
27 | | );
28 | * | _logTokenCoverage_Short_CreateDeposit(
29 | * | shortToken,
30 | | "ShortToken",
31 | * | _getTokenPrice(shortToken, tokenPrices)
32 | | );
33 | * | _logUserCoverage_CreateDeposit(user);
34 | * | _logLongAmountCoverage_CreateDeposit(longAmount);
35 | * | _logShortAmountCoverage_CreateDeposit(shortAmount);
36 | | }
37 | |
38 | * | function _logUserCoverage_CreateDeposit(address user) internal {
39 | * | if (user == USER0) {
40 | * | fl.log("User USER0 hit");
41 | | }
42 | * | if (user == USER1) {
43 | * | fl.log("User USER1 hit");
44 | | }
45 | * | if (user == USER2) {
46 | * | fl.log("User USER2 hit");
47 | | }
48 | * | if (user == USER3) {
49 | * | fl.log("User USER3 hit");
50 | | }
51 | * | if (user == USER4) {
52 | * | fl.log("User USER4 hit");
53 | | }
54 | * | if (user == USER5) {
55 | * | fl.log("User USER5 hit");
56 | | }
57 | * | if (user == USER6) {
58 | * | fl.log("User USER6 hit");
59 | | }
60 | * | if (user == USER7) {
61 | * | fl.log("User USER7 hit");
62 | | }
63 | * | if (user == USER8) {
64 | * | fl.log("User USER8 hit");
65 | | }
66 | * | if (user == USER9) {
67 | * | fl.log("User USER9 hit");
68 | | }
69 | * | if (user == USER10) {
70 | * | fl.log("User USER10 hit");
71 | | }
72 | * | if (user == USER11) {
73 | * | fl.log("User USER11 hit");
74 | | }
75 | * | if (user == USER12) {
76 | * | fl.log("User USER12 hit");
77 | | }
78 | * | if (user == USER13) {
79 | * | fl.log("User USER13 hit");
80 | | }
81 | | }
82 | |
83 | * | function _logMarketCoverage_CreateDeposit(address market) internal {
84 | * | if (market == market_0_WETH_USDC) {
85 | * | fl.log("Market market_0_WETH_USDC hit");
86 | | }
87 | |
88 | * | if (market == market_WBTC_WBTC_USDC) {
89 | * | fl.log("Market market_WBTC_WBTC_USDC hit");
90 | | }
91 | * | if (market == market_WETH_WETH_USDC) {
92 | * | fl.log("Market market_WETH_WETH_USDC hit");
93 | | }
94 | * | if (market == market_WETH_WETH_USDT) {
95 | * | fl.log("Market market_WETH_WETH_USDT hit");
96 | | }
97 | | }
98 | |
99 | | // /\_/\
100 | | // ( o.o )
101 | | // > ^ < CREATE DEPOSIT: LONGS
102 | |
103 | * | function _logTokenCoverage_Long_CreateDeposit(
104 | | address token,
105 | | string memory tokenType,
106 | | uint256 price
107 | | ) internal {
108 | * | if (token == address(WETH)) {
109 | * | fl.log(string(abi.encodePacked(tokenType, " WETH hit")));
110 | |
111 | * | _logWETHPriceBucket_Long_CreateDeposit(price, token);
112 | | }
113 | * | if (token == address(WBTC)) {
114 | * | fl.log(string(abi.encodePacked(tokenType, " WBTC hit")));
115 | |
116 | * | _logWBTCPriceBucket_Long_CreateDeposit(price, token);
117 | | }
118 | * | if (token == address(USDC)) {
119 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit")));
120 | | }
121 | * | if (token == address(USDT)) {
122 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit")));
123 | | }
124 | | }
125 | * | function _logLongAmountCoverage_CreateDeposit(uint256 amount) internal {
126 | * | if (amount >= 0 && amount < 1e6) {
127 | | fl.log("LongAmount bucket: 0 to 1e6");
128 | | }
129 | * | if (amount >= 1e6 && amount < 1e12) {
130 | * | fl.log("LongAmount bucket: 1e6 to 1e12");
131 | | }
132 | * | if (amount >= 1e12 && amount < 1e18) {
133 | * | fl.log("LongAmount bucket: 1e12 to 1e18");
134 | | }
135 | * | if (amount >= 1e18 && amount < 1e24) {
136 | * | fl.log("LongAmount bucket: 1e18 to 1e24)");
137 | | }
138 | * | if (amount >= 1e24) {
139 | | fl.log("LongAmount bucket: 1e4) and above");
140 | | }
141 | | }
142 | |
143 | * | function _logWETHPriceBucket_Long_CreateDeposit(
144 | | uint256 price,
145 | | address token
146 | | ) internal {
147 | * | if (
148 | * | price >= WETH_MIN_PRICE &&
149 | * | price < 10_000e4 * (10 ** _getPrecision(token))
150 | | ) {
151 | * | fl.log("WETH price from 1k to 10k was hit");
152 | | }
153 | * | if (
154 | * | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
155 | * | price < 100_000e4 * (10 ** _getPrecision(token))
156 | | ) {
157 | * | fl.log("WETH price from 10k to 100k was hit");
158 | | }
159 | * | if (
160 | * | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
161 | * | price < 300_000e4 * (10 ** _getPrecision(token))
162 | | ) {
163 | * | fl.log("WETH price from 100k to 300k was hit");
164 | | }
165 | * | if (
166 | * | price >= 300_000e4 * (10 ** _getPrecision(token)) &&
167 | * | price < 400_000e4 * (10 ** _getPrecision(token))
168 | | ) {
169 | * | fl.log("WETH price from 300k to 400k was hit");
170 | | }
171 | * | if (
172 | * | price >= 400_000e4 * (10 ** _getPrecision(token)) &&
173 | * | price < 500_000e4 * (10 ** _getPrecision(token))
174 | | ) {
175 | * | fl.log("WETH price from 400k to 500k was hit");
176 | | }
177 | * | if (
178 | * | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
179 | * | price < 600_000e4 * (10 ** _getPrecision(token))
180 | | ) {
181 | * | fl.log("WETH price from 500k to 600k was hit");
182 | | }
183 | * | if (
184 | * | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
185 | * | price < 700_000e4 * (10 ** _getPrecision(token))
186 | | ) {
187 | * | fl.log("WETH price from 600k to 700k was hit");
188 | | }
189 | * | if (
190 | * | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
191 | * | price < 800_000e4 * (10 ** _getPrecision(token))
192 | | ) {
193 | * | fl.log("WETH price from 700k to 800k was hit");
194 | | }
195 | * | if (
196 | * | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
197 | * | price < 900_000e4 * (10 ** _getPrecision(token))
198 | | ) {
199 | * | fl.log("WETH price from 800k to 900k was hit");
200 | | }
201 | * | if (
202 | * | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
203 | * | price < WETH_MAX_PRICE * (10 ** _getPrecision(token))
204 | | ) {
205 | * | fl.log("WETH price from 900k to 1m was hit");
206 | | }
207 | | }
208 | |
209 | * | function _logWBTCPriceBucket_Long_CreateDeposit(
210 | | uint256 price,
211 | | address token
212 | | ) internal {
213 | * | if (
214 | * | price >= WBTC_MIN_PRICE &&
215 | * | price < 10_000e2 * (10 ** _getPrecision(token))
216 | | ) {
217 | * | fl.log("WBTC price from 1k to 10k was hit");
218 | | }
219 | * | if (
220 | * | price >= 10_000e2 * (10 ** _getPrecision(token)) &&
221 | * | price < 100_000e2 * (10 ** _getPrecision(token))
222 | | ) {
223 | * | fl.log("WBTC price from 10k to 100k was hit");
224 | | }
225 | * | if (
226 | * | price >= 100_000e2 * (10 ** _getPrecision(token)) &&
227 | * | price < 300_000e2 * (10 ** _getPrecision(token))
228 | | ) {
229 | * | fl.log("WBTC price from 100k to 300k was hit");
230 | | }
231 | * | if (
232 | * | price >= 300_000e2 * (10 ** _getPrecision(token)) &&
233 | * | price < 400_000e2 * (10 ** _getPrecision(token))
234 | | ) {
235 | * | fl.log("WBTC price from 300k to 400k was hit");
236 | | }
237 | * | if (
238 | * | price >= 400_000e2 * (10 ** _getPrecision(token)) &&
239 | * | price < 500_000e2 * (10 ** _getPrecision(token))
240 | | ) {
241 | * | fl.log("WBTC price from 400k to 500k was hit");
242 | | }
243 | * | if (
244 | * | price >= 500_000e2 * (10 ** _getPrecision(token)) &&
245 | * | price < 600_000e2 * (10 ** _getPrecision(token))
246 | | ) {
247 | * | fl.log("WBTC price from 500k to 600k was hit");
248 | | }
249 | * | if (
250 | * | price >= 600_000e2 * (10 ** _getPrecision(token)) &&
251 | * | price < 700_000e2 * (10 ** _getPrecision(token))
252 | | ) {
253 | * | fl.log("WBTC price from 600k to 700k was hit");
254 | | }
255 | * | if (
256 | * | price >= 700_000e2 * (10 ** _getPrecision(token)) &&
257 | * | price < 800_000e2 * (10 ** _getPrecision(token))
258 | | ) {
259 | * | fl.log("WBTC price from 700k to 800k was hit");
260 | | }
261 | * | if (
262 | * | price >= 800_000e2 * (10 ** _getPrecision(token)) &&
263 | * | price < 900_000e2 * (10 ** _getPrecision(token))
264 | | ) {
265 | * | fl.log("WBTC price from 800k to 900k was hit");
266 | | }
267 | * | if (
268 | * | price >= 900_000e2 * (10 ** _getPrecision(token)) &&
269 | * | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token))
270 | | ) {
271 | * | fl.log("WBTC price from 900k to 1m was hit");
272 | | }
273 | | }
274 | |
275 | | // /\_/\
276 | | // ( o.o )
277 | | // > ^ < CREATE DEPOSIT: SHORTS
278 | |
279 | * | function _logTokenCoverage_Short_CreateDeposit(
280 | | address token,
281 | | string memory tokenType,
282 | | uint256 price
283 | | ) internal {
284 | * | if (token == address(WETH)) {
285 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit")));
286 | | _logWETHPriceBucket_Short_CreateDeposit(price, token);
287 | | }
288 | * | if (token == address(WBTC)) {
289 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit")));
290 | | _logWBTCPriceBucket_Short_CreateDeposit(price, token);
291 | | }
292 | * | if (token == address(USDC)) {
293 | * | fl.log(string(abi.encodePacked(tokenType, " USDC hit")));
294 | | }
295 | * | if (token == address(USDT)) {
296 | * | fl.log(string(abi.encodePacked(tokenType, " USDT hit")));
297 | | }
298 | * | if (token == address(SOL)) {
299 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit")));
300 | | }
301 | | }
302 | |
303 | * | function _logShortAmountCoverage_CreateDeposit(uint256 amount) internal {
304 | * | if (amount >= 0 && amount < 1e6) {
305 | | fl.log("ShortAmount bucket: 0 to 1e6");
306 | | }
307 | * | if (amount >= 1e6 && amount < 1e12) {
308 | * | fl.log("ShortAmount bucket: 1e6 to 1e12");
309 | | }
310 | * | if (amount >= 1e12 && amount < 1e18) {
311 | * | fl.log("ShortAmount bucket: 1e12 to 1e18");
312 | | }
313 | * | if (amount >= 1e18 && amount < 1e24) {
314 | | fl.log("ShortAmount bucket: 1e18 to 1e24");
315 | | }
316 | * | if (amount >= 1e24) {
317 | | fl.log("ShortAmount bucket: 1e24 and above");
318 | | }
319 | | }
320 | |
321 | | function _logWETHPriceBucket_Short_CreateDeposit(
322 | | uint256 price,
323 | | address token
324 | | ) internal {
325 | | if (
326 | | price >= WETH_MIN_PRICE &&
327 | | price < 10_000e4 * (10 ** _getPrecision(token))
328 | | ) {
329 | | fl.log("WETH price from 1k to 10k was hit");
330 | | }
331 | | if (
332 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
333 | | price < 100_000e4 * (10 ** _getPrecision(token))
334 | | ) {
335 | | fl.log("WETH price from 10k to 100k was hit");
336 | | }
337 | | if (
338 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
339 | | price < 300_000e4 * (10 ** _getPrecision(token))
340 | | ) {
341 | | fl.log("WETH price from 100k to 300k was hit");
342 | | }
343 | | if (
344 | | price >= 300_000e4 * (10 ** _getPrecision(token)) &&
345 | | price < 400_000e4 * (10 ** _getPrecision(token))
346 | | ) {
347 | | fl.log("WETH price from 300k to 400k was hit");
348 | | }
349 | | if (
350 | | price >= 400_000e4 * (10 ** _getPrecision(token)) &&
351 | | price < 500_000e4 * (10 ** _getPrecision(token))
352 | | ) {
353 | | fl.log("WETH price from 400k to 500k was hit");
354 | | }
355 | | if (
356 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
357 | | price < 600_000e4 * (10 ** _getPrecision(token))
358 | | ) {
359 | | fl.log("WETH price from 500k to 600k was hit");
360 | | }
361 | | if (
362 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
363 | | price < 700_000e4 * (10 ** _getPrecision(token))
364 | | ) {
365 | | fl.log("WETH price from 600k to 700k was hit");
366 | | }
367 | | if (
368 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
369 | | price < 800_000e4 * (10 ** _getPrecision(token))
370 | | ) {
371 | | fl.log("WETH price from 700k to 800k was hit");
372 | | }
373 | | if (
374 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
375 | | price < 900_000e4 * (10 ** _getPrecision(token))
376 | | ) {
377 | | fl.log("WETH price from 800k to 900k was hit");
378 | | }
379 | | if (
380 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
381 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token))
382 | | ) {
383 | | fl.log("WETH price from 900k to 1m was hit");
384 | | }
385 | | }
386 | | function _logWBTCPriceBucket_Short_CreateDeposit(
387 | | uint256 price,
388 | | address token
389 | | ) internal {
390 | | if (
391 | | price >= WBTC_MIN_PRICE &&
392 | | price < 10_000e2 * (10 ** _getPrecision(token))
393 | | ) {
394 | | fl.log("WBTC price from 1k to 10k was hit");
395 | | }
396 | | if (
397 | | price >= 10_000e2 * (10 ** _getPrecision(token)) &&
398 | | price < 100_000e2 * (10 ** _getPrecision(token))
399 | | ) {
400 | | fl.log("WBTC price from 10k to 100k was hit");
401 | | }
402 | | if (
403 | | price >= 100_000e2 * (10 ** _getPrecision(token)) &&
404 | | price < 300_000e2 * (10 ** _getPrecision(token))
405 | | ) {
406 | | fl.log("WBTC price from 100k to 300k was hit");
407 | | }
408 | | if (
409 | | price >= 300_000e2 * (10 ** _getPrecision(token)) &&
410 | | price < 400_000e2 * (10 ** _getPrecision(token))
411 | | ) {
412 | | fl.log("WBTC price from 300k to 400k was hit");
413 | | }
414 | | if (
415 | | price >= 400_000e2 * (10 ** _getPrecision(token)) &&
416 | | price < 500_000e2 * (10 ** _getPrecision(token))
417 | | ) {
418 | | fl.log("WBTC price from 400k to 500k was hit");
419 | | }
420 | | if (
421 | | price >= 500_000e2 * (10 ** _getPrecision(token)) &&
422 | | price < 600_000e2 * (10 ** _getPrecision(token))
423 | | ) {
424 | | fl.log("WBTC price from 500k to 600k was hit");
425 | | }
426 | | if (
427 | | price >= 600_000e2 * (10 ** _getPrecision(token)) &&
428 | | price < 700_000e2 * (10 ** _getPrecision(token))
429 | | ) {
430 | | fl.log("WBTC price from 600k to 700k was hit");
431 | | }
432 | | if (
433 | | price >= 700_000e2 * (10 ** _getPrecision(token)) &&
434 | | price < 800_000e2 * (10 ** _getPrecision(token))
435 | | ) {
436 | | fl.log("WBTC price from 700k to 800k was hit");
437 | | }
438 | | if (
439 | | price >= 800_000e2 * (10 ** _getPrecision(token)) &&
440 | | price < 900_000e2 * (10 ** _getPrecision(token))
441 | | ) {
442 | | fl.log("WBTC price from 800k to 900k was hit");
443 | | }
444 | | if (
445 | | price >= 900_000e2 * (10 ** _getPrecision(token)) &&
446 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token))
447 | | ) {
448 | | fl.log("WBTC price from 900k to 1m was hit");
449 | | }
450 | | }
451 | |
452 | | function _logSOLPriceBucket_Short_CreateDeposit(
453 | | uint256 price,
454 | | address token
455 | | ) internal {
456 | | if (
457 | | price >= SOL_MIN_PRICE &&
458 | | price < 100e4 * (10 ** _getPrecision(token))
459 | | ) {
460 | | fl.log("SOL price from 1 to 100 was hit");
461 | | }
462 | | if (
463 | | price >= 1000e4 * (10 ** _getPrecision(token)) &&
464 | | price < 10_000e4 * (10 ** _getPrecision(token))
465 | | ) {
466 | | fl.log("SOL price from 1k to 10k was hit");
467 | | }
468 | | if (
469 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
470 | | price < 100_000e4 * (10 ** _getPrecision(token))
471 | | ) {
472 | | fl.log("SOL price from 10k to 100k was hit");
473 | | }
474 | | if (
475 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
476 | | price < 200_000e4 * (10 ** _getPrecision(token))
477 | | ) {
478 | | fl.log("SOL price from 100k to 200k was hit");
479 | | }
480 | | if (
481 | | price >= 200_000e4 * (10 ** _getPrecision(token)) &&
482 | | price < 500_000e4 * (10 ** _getPrecision(token))
483 | | ) {
484 | | fl.log("SOL price from 200k to 500k was hit");
485 | | }
486 | | if (
487 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
488 | | price < 600_000e4 * (10 ** _getPrecision(token))
489 | | ) {
490 | | fl.log("SOL price from 500k to 600k was hit");
491 | | }
492 | | if (
493 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
494 | | price < 700_000e4 * (10 ** _getPrecision(token))
495 | | ) {
496 | | fl.log("SOL price from 600k to 700k was hit");
497 | | }
498 | | if (
499 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
500 | | price < 800_000e4 * (10 ** _getPrecision(token))
501 | | ) {
502 | | fl.log("SOL price from 700k to 800k was hit");
503 | | }
504 | | if (
505 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
506 | | price < 900_000e4 * (10 ** _getPrecision(token))
507 | | ) {
508 | | fl.log("SOL price from 800k to 900k was hit");
509 | | }
510 | | if (
511 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
512 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token))
513 | | ) {
514 | | fl.log("SOL price from 900k to 1m was hit");
515 | | }
516 | | }
517 | |
518 | | // /\_/\ ___
519 | | // = o_o =_______ \ \ CANCEL DEPOSIT COVERAGE
520 | | // __^ __( \.__) )
521 | | // (@)<_____>__(_____)____/
522 | |
523 | | function _checkCancelDepositCoverage(
524 | | address market,
525 | | address longToken,
526 | | address shortToken,
527 | | TokenPrices memory tokenPrices,
528 | | address user,
529 | | uint longAmount,
530 | | uint shortAmount
531 | | ) internal {
532 | | _logMarketCoverage_CancelDeposit(market);
533 | | _logTokenCoverage_Long_CancelDeposit(
534 | | longToken,
535 | | "LongToken",
536 | | _getTokenPrice(longToken, tokenPrices)
537 | | );
538 | | _logTokenCoverage_Short_CancelDeposit(
539 | | shortToken,
540 | | "ShortToken",
541 | | _getTokenPrice(shortToken, tokenPrices)
542 | | );
543 | | _logUserCoverage_CancelDeposit(user);
544 | | _logLongAmountCoverage_CancelDeposit(longAmount);
545 | | _logShortAmountCoverage_CancelDeposit(shortAmount);
546 | | }
547 | |
548 | | function _logUserCoverage_CancelDeposit(address user) internal {
549 | | if (user == USER0) {
550 | | fl.log("User USER0 hit");
551 | | }
552 | | if (user == USER1) {
553 | | fl.log("User USER1 hit");
554 | | }
555 | | if (user == USER2) {
556 | | fl.log("User USER2 hit");
557 | | }
558 | | if (user == USER3) {
559 | | fl.log("User USER3 hit");
560 | | }
561 | | if (user == USER4) {
562 | | fl.log("User USER4 hit");
563 | | }
564 | | if (user == USER5) {
565 | | fl.log("User USER5 hit");
566 | | }
567 | | if (user == USER6) {
568 | | fl.log("User USER6 hit");
569 | | }
570 | | if (user == USER7) {
571 | | fl.log("User USER7 hit");
572 | | }
573 | | if (user == USER8) {
574 | | fl.log("User USER8 hit");
575 | | }
576 | | if (user == USER9) {
577 | | fl.log("User USER9 hit");
578 | | }
579 | | if (user == USER10) {
580 | | fl.log("User USER10 hit");
581 | | }
582 | | if (user == USER11) {
583 | | fl.log("User USER11 hit");
584 | | }
585 | | if (user == USER12) {
586 | | fl.log("User USER12 hit");
587 | | }
588 | | if (user == USER13) {
589 | | fl.log("User USER13 hit");
590 | | }
591 | | }
592 | |
593 | | function _logMarketCoverage_CancelDeposit(address market) internal {
594 | | if (market == market_0_WETH_USDC) {
595 | | fl.log("Market market_0_WETH_USDC hit");
596 | | }
597 | |
598 | | if (market == market_WBTC_WBTC_USDC) {
599 | | fl.log("Market market_WBTC_WBTC_USDC hit");
600 | | }
601 | | if (market == market_WETH_WETH_USDC) {
602 | | fl.log("Market market_WETH_WETH_USDC hit");
603 | | }
604 | | if (market == market_WETH_WETH_USDT) {
605 | | fl.log("Market market_WETH_WETH_USDT hit");
606 | | }
607 | | }
608 | |
609 | | // /\_/\
610 | | // ( o.o )
611 | | // > ^ < CANCEL DEPOSIT: LONGS
612 | |
613 | | function _logTokenCoverage_Long_CancelDeposit(
614 | | address token,
615 | | string memory tokenType,
616 | | uint256 price
617 | | ) internal {
618 | | if (token == address(WETH)) {
619 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit")));
620 | | _logWETHPriceBucket_Long_CancelDeposit(price, token);
621 | | }
622 | | if (token == address(WBTC)) {
623 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit")));
624 | | _logWBTCPriceBucket_Long_CancelDeposit(price, token);
625 | | }
626 | | if (token == address(USDC)) {
627 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit")));
628 | | }
629 | | if (token == address(USDT)) {
630 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit")));
631 | | }
632 | |
633 | | if (token == address(SOL)) {
634 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit")));
635 | | _logSOLPriceBucket_Long_CancelDeposit(price, token);
636 | | }
637 | | }
638 | |
639 | | function _logLongAmountCoverage_CancelDeposit(uint256 amount) internal {
640 | | if (amount >= 0 && amount < 1e6) {
641 | | fl.log("LongAmount bucket: 0 to 1e6");
642 | | }
643 | | if (amount >= 1e6 && amount < 1e12) {
644 | | fl.log("LongAmount bucket: 1e6 to 1e12");
645 | | }
646 | | if (amount >= 1e12 && amount < 1e18) {
647 | | fl.log("LongAmount bucket: 1e12 to 1e18");
648 | | }
649 | | if (amount >= 1e18 && amount < 1e24) {
650 | | fl.log("LongAmount bucket: 1e18 to 1e24)");
651 | | }
652 | | if (amount >= 1e24) {
653 | | fl.log("LongAmount bucket: 1e4) and above");
654 | | }
655 | | }
656 | |
657 | | function _logWETHPriceBucket_Long_CancelDeposit(
658 | | uint256 price,
659 | | address token
660 | | ) internal {
661 | | if (
662 | | price >= WETH_MIN_PRICE &&
663 | | price < 10_000e4 * (10 ** _getPrecision(token))
664 | | ) {
665 | | fl.log("WETH price from 1k to 10k was hit");
666 | | }
667 | | if (
668 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
669 | | price < 100_000e4 * (10 ** _getPrecision(token))
670 | | ) {
671 | | fl.log("WETH price from 10k to 100k was hit");
672 | | }
673 | | if (
674 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
675 | | price < 300_000e4 * (10 ** _getPrecision(token))
676 | | ) {
677 | | fl.log("WETH price from 100k to 300k was hit");
678 | | }
679 | | if (
680 | | price >= 300_000e4 * (10 ** _getPrecision(token)) &&
681 | | price < 400_000e4 * (10 ** _getPrecision(token))
682 | | ) {
683 | | fl.log("WETH price from 300k to 400k was hit");
684 | | }
685 | | if (
686 | | price >= 400_000e4 * (10 ** _getPrecision(token)) &&
687 | | price < 500_000e4 * (10 ** _getPrecision(token))
688 | | ) {
689 | | fl.log("WETH price from 400k to 500k was hit");
690 | | }
691 | | if (
692 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
693 | | price < 600_000e4 * (10 ** _getPrecision(token))
694 | | ) {
695 | | fl.log("WETH price from 500k to 600k was hit");
696 | | }
697 | | if (
698 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
699 | | price < 700_000e4 * (10 ** _getPrecision(token))
700 | | ) {
701 | | fl.log("WETH price from 600k to 700k was hit");
702 | | }
703 | | if (
704 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
705 | | price < 800_000e4 * (10 ** _getPrecision(token))
706 | | ) {
707 | | fl.log("WETH price from 700k to 800k was hit");
708 | | }
709 | | if (
710 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
711 | | price < 900_000e4 * (10 ** _getPrecision(token))
712 | | ) {
713 | | fl.log("WETH price from 800k to 900k was hit");
714 | | }
715 | | if (
716 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
717 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token))
718 | | ) {
719 | | fl.log("WETH price from 900k to 1m was hit");
720 | | }
721 | | }
722 | | function _logWBTCPriceBucket_Long_CancelDeposit(
723 | | uint256 price,
724 | | address token
725 | | ) internal {
726 | | if (
727 | | price >= WBTC_MIN_PRICE &&
728 | | price < 10_000e2 * (10 ** _getPrecision(token))
729 | | ) {
730 | | fl.log("WBTC price from 1k to 10k was hit");
731 | | }
732 | | if (
733 | | price >= 10_000e2 * (10 ** _getPrecision(token)) &&
734 | | price < 100_000e2 * (10 ** _getPrecision(token))
735 | | ) {
736 | | fl.log("WBTC price from 10k to 100k was hit");
737 | | }
738 | | if (
739 | | price >= 100_000e2 * (10 ** _getPrecision(token)) &&
740 | | price < 300_000e2 * (10 ** _getPrecision(token))
741 | | ) {
742 | | fl.log("WBTC price from 100k to 300k was hit");
743 | | }
744 | | if (
745 | | price >= 300_000e2 * (10 ** _getPrecision(token)) &&
746 | | price < 400_000e2 * (10 ** _getPrecision(token))
747 | | ) {
748 | | fl.log("WBTC price from 300k to 400k was hit");
749 | | }
750 | | if (
751 | | price >= 400_000e2 * (10 ** _getPrecision(token)) &&
752 | | price < 500_000e2 * (10 ** _getPrecision(token))
753 | | ) {
754 | | fl.log("WBTC price from 400k to 500k was hit");
755 | | }
756 | | if (
757 | | price >= 500_000e2 * (10 ** _getPrecision(token)) &&
758 | | price < 600_000e2 * (10 ** _getPrecision(token))
759 | | ) {
760 | | fl.log("WBTC price from 500k to 600k was hit");
761 | | }
762 | | if (
763 | | price >= 600_000e2 * (10 ** _getPrecision(token)) &&
764 | | price < 700_000e2 * (10 ** _getPrecision(token))
765 | | ) {
766 | | fl.log("WBTC price from 600k to 700k was hit");
767 | | }
768 | | if (
769 | | price >= 700_000e2 * (10 ** _getPrecision(token)) &&
770 | | price < 800_000e2 * (10 ** _getPrecision(token))
771 | | ) {
772 | | fl.log("WBTC price from 700k to 800k was hit");
773 | | }
774 | | if (
775 | | price >= 800_000e2 * (10 ** _getPrecision(token)) &&
776 | | price < 900_000e2 * (10 ** _getPrecision(token))
777 | | ) {
778 | | fl.log("WBTC price from 800k to 900k was hit");
779 | | }
780 | | if (
781 | | price >= 900_000e2 * (10 ** _getPrecision(token)) &&
782 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token))
783 | | ) {
784 | | fl.log("WBTC price from 900k to 1m was hit");
785 | | }
786 | | }
787 | | function _logSOLPriceBucket_Long_CancelDeposit(
788 | | uint256 price,
789 | | address token
790 | | ) internal {
791 | | if (
792 | | price >= SOL_MIN_PRICE &&
793 | | price < 100e4 * (10 ** _getPrecision(token))
794 | | ) {
795 | | fl.log("SOL price from 1 to 100 was hit");
796 | | }
797 | | if (
798 | | price >= 1000e4 * (10 ** _getPrecision(token)) &&
799 | | price < 10_000e4 * (10 ** _getPrecision(token))
800 | | ) {
801 | | fl.log("SOL price from 1k to 10k was hit");
802 | | }
803 | | if (
804 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
805 | | price < 100_000e4 * (10 ** _getPrecision(token))
806 | | ) {
807 | | fl.log("SOL price from 10k to 100k was hit");
808 | | }
809 | | if (
810 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
811 | | price < 200_000e4 * (10 ** _getPrecision(token))
812 | | ) {
813 | | fl.log("SOL price from 100k to 200k was hit");
814 | | }
815 | | if (
816 | | price >= 200_000e4 * (10 ** _getPrecision(token)) &&
817 | | price < 500_000e4 * (10 ** _getPrecision(token))
818 | | ) {
819 | | fl.log("SOL price from 200k to 500k was hit");
820 | | }
821 | | if (
822 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
823 | | price < 600_000e4 * (10 ** _getPrecision(token))
824 | | ) {
825 | | fl.log("SOL price from 500k to 600k was hit");
826 | | }
827 | | if (
828 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
829 | | price < 700_000e4 * (10 ** _getPrecision(token))
830 | | ) {
831 | | fl.log("SOL price from 600k to 700k was hit");
832 | | }
833 | | if (
834 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
835 | | price < 800_000e4 * (10 ** _getPrecision(token))
836 | | ) {
837 | | fl.log("SOL price from 700k to 800k was hit");
838 | | }
839 | | if (
840 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
841 | | price < 900_000e4 * (10 ** _getPrecision(token))
842 | | ) {
843 | | fl.log("SOL price from 800k to 900k was hit");
844 | | }
845 | | if (
846 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
847 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token))
848 | | ) {
849 | | fl.log("SOL price from 900k to 1m was hit");
850 | | }
851 | | }
852 | |
853 | | // /\_/\
854 | | // ( o.o )
855 | | // > ^ < CANCEL DEPOSIT: SHORTS
856 | |
857 | | function _logTokenCoverage_Short_CancelDeposit(
858 | | address token,
859 | | string memory tokenType,
860 | | uint256 price
861 | | ) internal {
862 | | if (token == address(WETH)) {
863 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit")));
864 | | _logWETHPriceBucket_Short_CancelDeposit(price, token);
865 | | }
866 | | if (token == address(WBTC)) {
867 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit")));
868 | | _logWBTCPriceBucket_Short_CancelDeposit(price, token);
869 | | }
870 | | if (token == address(USDC)) {
871 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit")));
872 | | }
873 | | if (token == address(USDT)) {
874 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit")));
875 | | }
876 | | if (token == address(SOL)) {
877 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit")));
878 | | _logSOLPriceBucket_Short_CancelDeposit(price, token);
879 | | }
880 | | }
881 | |
882 | | function _logShortAmountCoverage_CancelDeposit(uint256 amount) internal {
883 | | if (amount >= 0 && amount < 1e6) {
884 | | fl.log("ShortAmount bucket: 0 to 1e6");
885 | | }
886 | | if (amount >= 1e6 && amount < 1e12) {
887 | | fl.log("ShortAmount bucket: 1e6 to 1e12");
888 | | }
889 | | if (amount >= 1e12 && amount < 1e18) {
890 | | fl.log("ShortAmount bucket: 1e12 to 1e18");
891 | | }
892 | | if (amount >= 1e18 && amount < 1e24) {
893 | | fl.log("ShortAmount bucket: 1e18 to 1e24");
894 | | }
895 | | if (amount >= 1e24) {
896 | | fl.log("ShortAmount bucket: 1e24 and above");
897 | | }
898 | | }
899 | |
900 | | function _logWETHPriceBucket_Short_CancelDeposit(
901 | | uint256 price,
902 | | address token
903 | | ) internal {
904 | | if (
905 | | price >= WETH_MIN_PRICE &&
906 | | price < 10_000e4 * (10 ** _getPrecision(token))
907 | | ) {
908 | | fl.log("WETH price from 1k to 10k was hit");
909 | | }
910 | | if (
911 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
912 | | price < 100_000e4 * (10 ** _getPrecision(token))
913 | | ) {
914 | | fl.log("WETH price from 10k to 100k was hit");
915 | | }
916 | | if (
917 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
918 | | price < 300_000e4 * (10 ** _getPrecision(token))
919 | | ) {
920 | | fl.log("WETH price from 100k to 300k was hit");
921 | | }
922 | | if (
923 | | price >= 300_000e4 * (10 ** _getPrecision(token)) &&
924 | | price < 400_000e4 * (10 ** _getPrecision(token))
925 | | ) {
926 | | fl.log("WETH price from 300k to 400k was hit");
927 | | }
928 | | if (
929 | | price >= 400_000e4 * (10 ** _getPrecision(token)) &&
930 | | price < 500_000e4 * (10 ** _getPrecision(token))
931 | | ) {
932 | | fl.log("WETH price from 400k to 500k was hit");
933 | | }
934 | | if (
935 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
936 | | price < 600_000e4 * (10 ** _getPrecision(token))
937 | | ) {
938 | | fl.log("WETH price from 500k to 600k was hit");
939 | | }
940 | | if (
941 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
942 | | price < 700_000e4 * (10 ** _getPrecision(token))
943 | | ) {
944 | | fl.log("WETH price from 600k to 700k was hit");
945 | | }
946 | | if (
947 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
948 | | price < 800_000e4 * (10 ** _getPrecision(token))
949 | | ) {
950 | | fl.log("WETH price from 700k to 800k was hit");
951 | | }
952 | | if (
953 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
954 | | price < 900_000e4 * (10 ** _getPrecision(token))
955 | | ) {
956 | | fl.log("WETH price from 800k to 900k was hit");
957 | | }
958 | | if (
959 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
960 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token))
961 | | ) {
962 | | fl.log("WETH price from 900k to 1m was hit");
963 | | }
964 | | }
965 | | function _logWBTCPriceBucket_Short_CancelDeposit(
966 | | uint256 price,
967 | | address token
968 | | ) internal {
969 | | if (
970 | | price >= WBTC_MIN_PRICE &&
971 | | price < 10_000e2 * (10 ** _getPrecision(token))
972 | | ) {
973 | | fl.log("WBTC price from 1k to 10k was hit");
974 | | }
975 | | if (
976 | | price >= 10_000e2 * (10 ** _getPrecision(token)) &&
977 | | price < 100_000e2 * (10 ** _getPrecision(token))
978 | | ) {
979 | | fl.log("WBTC price from 10k to 100k was hit");
980 | | }
981 | | if (
982 | | price >= 100_000e2 * (10 ** _getPrecision(token)) &&
983 | | price < 300_000e2 * (10 ** _getPrecision(token))
984 | | ) {
985 | | fl.log("WBTC price from 100k to 300k was hit");
986 | | }
987 | | if (
988 | | price >= 300_000e2 * (10 ** _getPrecision(token)) &&
989 | | price < 400_000e2 * (10 ** _getPrecision(token))
990 | | ) {
991 | | fl.log("WBTC price from 300k to 400k was hit");
992 | | }
993 | | if (
994 | | price >= 400_000e2 * (10 ** _getPrecision(token)) &&
995 | | price < 500_000e2 * (10 ** _getPrecision(token))
996 | | ) {
997 | | fl.log("WBTC price from 400k to 500k was hit");
998 | | }
999 | | if (
1000 | | price >= 500_000e2 * (10 ** _getPrecision(token)) &&
1001 | | price < 600_000e2 * (10 ** _getPrecision(token))
1002 | | ) {
1003 | | fl.log("WBTC price from 500k to 600k was hit");
1004 | | }
1005 | | if (
1006 | | price >= 600_000e2 * (10 ** _getPrecision(token)) &&
1007 | | price < 700_000e2 * (10 ** _getPrecision(token))
1008 | | ) {
1009 | | fl.log("WBTC price from 600k to 700k was hit");
1010 | | }
1011 | | if (
1012 | | price >= 700_000e2 * (10 ** _getPrecision(token)) &&
1013 | | price < 800_000e2 * (10 ** _getPrecision(token))
1014 | | ) {
1015 | | fl.log("WBTC price from 700k to 800k was hit");
1016 | | }
1017 | | if (
1018 | | price >= 800_000e2 * (10 ** _getPrecision(token)) &&
1019 | | price < 900_000e2 * (10 ** _getPrecision(token))
1020 | | ) {
1021 | | fl.log("WBTC price from 800k to 900k was hit");
1022 | | }
1023 | | if (
1024 | | price >= 900_000e2 * (10 ** _getPrecision(token)) &&
1025 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token))
1026 | | ) {
1027 | | fl.log("WBTC price from 900k to 1m was hit");
1028 | | }
1029 | | }
1030 | |
1031 | | function _logSOLPriceBucket_Short_CancelDeposit(
1032 | | uint256 price,
1033 | | address token
1034 | | ) internal {
1035 | | if (
1036 | | price >= SOL_MIN_PRICE &&
1037 | | price < 100e4 * (10 ** _getPrecision(token))
1038 | | ) {
1039 | | fl.log("SOL price from 1 to 100 was hit");
1040 | | }
1041 | | if (
1042 | | price >= 1000e4 * (10 ** _getPrecision(token)) &&
1043 | | price < 10_000e4 * (10 ** _getPrecision(token))
1044 | | ) {
1045 | | fl.log("SOL price from 1k to 10k was hit");
1046 | | }
1047 | | if (
1048 | | price >= 10_000e4 * (10 ** _getPrecision(token)) &&
1049 | | price < 100_000e4 * (10 ** _getPrecision(token))
1050 | | ) {
1051 | | fl.log("SOL price from 10k to 100k was hit");
1052 | | }
1053 | | if (
1054 | | price >= 100_000e4 * (10 ** _getPrecision(token)) &&
1055 | | price < 200_000e4 * (10 ** _getPrecision(token))
1056 | | ) {
1057 | | fl.log("SOL price from 100k to 200k was hit");
1058 | | }
1059 | | if (
1060 | | price >= 200_000e4 * (10 ** _getPrecision(token)) &&
1061 | | price < 500_000e4 * (10 ** _getPrecision(token))
1062 | | ) {
1063 | | fl.log("SOL price from 200k to 500k was hit");
1064 | | }
1065 | | if (
1066 | | price >= 500_000e4 * (10 ** _getPrecision(token)) &&
1067 | | price < 600_000e4 * (10 ** _getPrecision(token))
1068 | | ) {
1069 | | fl.log("SOL price from 500k to 600k was hit");
1070 | | }
1071 | | if (
1072 | | price >= 600_000e4 * (10 ** _getPrecision(token)) &&
1073 | | price < 700_000e4 * (10 ** _getPrecision(token))
1074 | | ) {
1075 | | fl.log("SOL price from 600k to 700k was hit");
1076 | | }
1077 | | if (
1078 | | price >= 700_000e4 * (10 ** _getPrecision(token)) &&
1079 | | price < 800_000e4 * (10 ** _getPrecision(token))
1080 | | ) {
1081 | | fl.log("SOL price from 700k to 800k was hit");
1082 | | }
1083 | | if (
1084 | | price >= 800_000e4 * (10 ** _getPrecision(token)) &&
1085 | | price < 900_000e4 * (10 ** _getPrecision(token))
1086 | | ) {
1087 | | fl.log("SOL price from 800k to 900k was hit");
1088 | | }
1089 | | if (
1090 | | price >= 900_000e4 * (10 ** _getPrecision(token)) &&
1091 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token))
1092 | | ) {
1093 | | fl.log("SOL price from 900k to 1m was hit");
1094 | | }
1095 | | }
1096 | |
1097 | | // /\_/\ ___
1098 | | // = o_o =_______ \ \ EXECUTE DEPOSIT COVERAGE
1099 | | // __^ __( \.__) )
1100 | | // (@)<_____>__(_____)____/
1101 | |
1102 | * | function _checkCoverageAfterDepositExecution(
1103 | | address market,
1104 | | uint userBalance,
1105 | | uint marketTotalSupply
1106 | | ) internal {
1107 | * | _logMarketTokenBySupplyCoverage_ExecuteDeposit(
1108 | * | market,
1109 | * | marketTotalSupply
1110 | | );
1111 | * | _logMarketAmountByUser(userBalance);
1112 | | }
1113 | |
1114 | * | function _logMarketTokenBySupplyCoverage_ExecuteDeposit(
1115 | | address token,
1116 | | uint256 totalSupply
1117 | | ) internal {
1118 | * | if (token == address(market_0_WETH_USDC)) {
1119 | | if (totalSupply >= 0 && totalSupply < 1e6) {
1120 | | fl.log("TotalSupply bucket: 0 to 1e6");
1121 | | }
1122 | | if (totalSupply >= 1e6 && totalSupply < 1e12) {
1123 | | fl.log("TotalSupply bucket: 1e6 to 1e12");
1124 | | }
1125 | | if (totalSupply >= 1e12 && totalSupply < 1e18) {
1126 | | fl.log("TotalSupply bucket: 1e12 to 1e18");
1127 | | }
1128 | | if (totalSupply >= 1e18 && totalSupply < 1e24) {
1129 | | fl.log("TotalSupply bucket: 1e18 to 1e24");
1130 | | }
1131 | | if (totalSupply >= 1e24) {
1132 | | fl.log("TotalSupply bucket: 1e24 and above");
1133 | | }
1134 | | }
1135 | |
1136 | * | if (token == address(market_WBTC_WBTC_USDC)) {
1137 | | if (totalSupply >= 0 && totalSupply < 1e6) {
1138 | | fl.log("TotalSupply bucket: 0 to 1e6");
1139 | | }
1140 | | if (totalSupply >= 1e6 && totalSupply < 1e12) {
1141 | | fl.log("TotalSupply bucket: 1e6 to 1e12");
1142 | | }
1143 | | if (totalSupply >= 1e12 && totalSupply < 1e18) {
1144 | | fl.log("TotalSupply bucket: 1e12 to 1e18");
1145 | | }
1146 | | if (totalSupply >= 1e18 && totalSupply < 1e24) {
1147 | | fl.log("TotalSupply bucket: 1e18 to 1e24");
1148 | | }
1149 | | if (totalSupply >= 1e24) {
1150 | | fl.log("TotalSupply bucket: 1e24 and above");
1151 | | }
1152 | | }
1153 | * | if (token == address(market_WETH_WETH_USDC)) {
1154 | | if (totalSupply >= 0 && totalSupply < 1e6) {
1155 | | fl.log("TotalSupply bucket: 0 to 1e6");
1156 | | }
1157 | | if (totalSupply >= 1e6 && totalSupply < 1e12) {
1158 | | fl.log("TotalSupply bucket: 1e6 to 1e12");
1159 | | }
1160 | | if (totalSupply >= 1e12 && totalSupply < 1e18) {
1161 | | fl.log("TotalSupply bucket: 1e12 to 1e18");
1162 | | }
1163 | | if (totalSupply >= 1e18 && totalSupply < 1e24) {
1164 | | fl.log("TotalSupply bucket: 1e18 to 1e24");
1165 | | }
1166 | | if (totalSupply >= 1e24) {
1167 | | fl.log("TotalSupply bucket: 1e24 and above");
1168 | | }
1169 | | }
1170 | * | if (token == address(market_WETH_WETH_USDT)) {
1171 | | if (totalSupply >= 0 && totalSupply < 1e6) {
1172 | | fl.log("TotalSupply bucket: 0 to 1e6");
1173 | | }
1174 | | if (totalSupply >= 1e6 && totalSupply < 1e12) {
1175 | | fl.log("TotalSupply bucket: 1e6 to 1e12");
1176 | | }
1177 | | if (totalSupply >= 1e12 && totalSupply < 1e18) {
1178 | | fl.log("TotalSupply bucket: 1e12 to 1e18");
1179 | | }
1180 | | if (totalSupply >= 1e18 && totalSupply < 1e24) {
1181 | | fl.log("TotalSupply bucket: 1e18 to 1e24");
1182 | | }
1183 | | if (totalSupply >= 1e24) {
1184 | | fl.log("TotalSupply bucket: 1e24 and above");
1185 | | }
1186 | | }
1187 | | }
1188 | |
1189 | * | function _logMarketAmountByUser(uint256 amount) internal {
1190 | * | if (amount >= 0 && amount < 1e6) {
1191 | * | fl.log("Amount bucket: 0 to 1e6");
1192 | | }
1193 | * | if (amount >= 1e6 && amount < 1e12) {
1194 | | fl.log("Amount bucket: 1e6 to 1e12");
1195 | | }
1196 | * | if (amount >= 1e12 && amount < 1e18) {
1197 | | fl.log("Amount bucket: 1e12 to 1e18");
1198 | | }
1199 | * | if (amount >= 1e18 && amount < 1e24) {
1200 | * | fl.log("Amount bucket: 1e18 to 1e24");
1201 | | }
1202 | * | if (amount >= 1e24) {
1203 | * | fl.log("Amount bucket: 1e24 and above");
1204 | | }
1205 | | }
1206 | | }
1207 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/LiquidationCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../properties/BeforeAfter.sol";
6 | |
7 | | contract LiquidationCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ LIQUIDATION COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | * | function _checkPositionLiquitatableCoverage(
14 | | address account,
15 | | address market,
16 | | address collateralToken,
17 | | bool isLong,
18 | | PositionUtils.IsPositionLiquidatableInfo
19 | | memory isPositionLiquidatableInfo
20 | | ) internal {
21 | * | _logLiquidationAccountCoverage(account);
22 | * | _logLiquidationMarketCoverage(market);
23 | * | _logLiquidationCollateralTokenCoverage(collateralToken);
24 | * | _logLiquidationIsLongCoverage(isLong);
25 | * | _logRemainingCollateralUsdCoverage(
26 | * | isPositionLiquidatableInfo.remainingCollateralUsd
27 | | );
28 | * | _logMinCollateralUsdCoverage(
29 | * | isPositionLiquidatableInfo.minCollateralUsd
30 | | );
31 | * | _logMinCollateralUsdForLeverageCoverage(
32 | * | isPositionLiquidatableInfo.minCollateralUsdForLeverage
33 | | );
34 | | }
35 | |
36 | * | function _logLiquidationIsLongCoverage(bool isLong) internal {
37 | * | if (isLong) {
38 | * | fl.log("Liquidation isLong is true");
39 | | } else {
40 | | fl.log("Liquidation isLong is false");
41 | | }
42 | | }
43 | |
44 | * | function _logLiquidationAccountCoverage(address account) internal {
45 | * | if (account == USER0) {
46 | | fl.log("Account USER0 hit");
47 | | }
48 | * | if (account == USER1) {
49 | | fl.log("Account USER1 hit");
50 | | }
51 | * | if (account == USER2) {
52 | | fl.log("Account USER2 hit");
53 | | }
54 | * | if (account == USER3) {
55 | | fl.log("Account USER3 hit");
56 | | }
57 | * | if (account == USER4) {
58 | | fl.log("Account USER4 hit");
59 | | }
60 | * | if (account == USER5) {
61 | | fl.log("Account USER5 hit");
62 | | }
63 | * | if (account == USER6) {
64 | | fl.log("Account USER6 hit");
65 | | }
66 | * | if (account == USER7) {
67 | | fl.log("Account USER7 hit");
68 | | }
69 | * | if (account == USER8) {
70 | | fl.log("Account USER8 hit");
71 | | }
72 | * | if (account == USER9) {
73 | | fl.log("Account USER9 hit");
74 | | }
75 | * | if (account == USER10) {
76 | | fl.log("Account USER10 hit");
77 | | }
78 | * | if (account == USER11) {
79 | | fl.log("Account USER11 hit");
80 | | }
81 | * | if (account == USER12) {
82 | | fl.log("Account USER12 hit");
83 | | }
84 | * | if (account == USER13) {
85 | | fl.log("Account USER13 hit");
86 | | }
87 | | }
88 | |
89 | * | function _logLiquidationMarketCoverage(address market) internal {
90 | * | if (market == address(market_0_WETH_USDC)) {
91 | | fl.log("Market market_0_WETH_USDC hit");
92 | | }
93 | |
94 | * | if (market == address(market_WBTC_WBTC_USDC)) {
95 | * | fl.log("Market market_WBTC_WBTC_USDC hit");
96 | | }
97 | * | if (market == address(market_WETH_WETH_USDC)) {
98 | * | fl.log("Market market_WETH_WETH_USDC hit");
99 | | }
100 | * | if (market == address(market_WETH_WETH_USDT)) {
101 | | fl.log("Market market_WETH_WETH_USDT hit");
102 | | }
103 | | }
104 | |
105 | * | function _logLiquidationCollateralTokenCoverage(
106 | | address collateralToken
107 | | ) internal {
108 | * | if (collateralToken == address(WETH)) {
109 | | fl.log("CollateralToken is WETH");
110 | | }
111 | * | if (collateralToken == address(WBTC)) {
112 | | fl.log("CollateralToken is WBTC");
113 | | }
114 | * | if (collateralToken == address(USDC)) {
115 | * | fl.log("CollateralToken is USDC");
116 | | }
117 | * | if (collateralToken == address(USDT)) {
118 | | fl.log("CollateralToken is USDT");
119 | | }
120 | * | if (collateralToken == address(SOL)) {
121 | | fl.log("CollateralToken is SOL");
122 | | }
123 | | }
124 | * | function _logRemainingCollateralUsdCoverage(
125 | | int256 remainingCollateralUsd
126 | | ) internal {
127 | * | if (remainingCollateralUsd == 0) {
128 | | fl.log("RemainingCollateralUsd is 0");
129 | | }
130 | * | if (remainingCollateralUsd > 0 && remainingCollateralUsd <= 1e6) {
131 | | fl.log("RemainingCollateralUsd is between 0 and 1e6");
132 | | }
133 | * | if (remainingCollateralUsd > 1e6 && remainingCollateralUsd <= 1e12) {
134 | | fl.log("RemainingCollateralUsd is between 1e6 and 1e12");
135 | | }
136 | * | if (remainingCollateralUsd > 1e12 && remainingCollateralUsd <= 1e18) {
137 | | fl.log("RemainingCollateralUsd is between 1e12 and 1e18");
138 | | }
139 | * | if (remainingCollateralUsd > 1e18 && remainingCollateralUsd <= 1e24) {
140 | | fl.log("RemainingCollateralUsd is between 1e18 and 1e24");
141 | | }
142 | * | if (remainingCollateralUsd > 1e24) {
143 | | fl.log("RemainingCollateralUsd is greater than 1e24");
144 | | }
145 | * | if (remainingCollateralUsd < 0 && remainingCollateralUsd >= -1e6) {
146 | | fl.log("RemainingCollateralUsd is between 0 and -1e6");
147 | | }
148 | * | if (remainingCollateralUsd < -1e6 && remainingCollateralUsd >= -1e12) {
149 | | fl.log("RemainingCollateralUsd is between -1e6 and -1e12");
150 | | }
151 | * | if (remainingCollateralUsd < -1e12 && remainingCollateralUsd >= -1e18) {
152 | | fl.log("RemainingCollateralUsd is between -1e12 and -1e18");
153 | | }
154 | * | if (remainingCollateralUsd < -1e18 && remainingCollateralUsd >= -1e24) {
155 | | fl.log("RemainingCollateralUsd is between -1e18 and -1e24");
156 | | }
157 | * | if (remainingCollateralUsd < -1e24) {
158 | * | fl.log("RemainingCollateralUsd is less than -1e24");
159 | | }
160 | | }
161 | |
162 | * | function _logMinCollateralUsdCoverage(int256 minCollateralUsd) internal {
163 | * | if (minCollateralUsd == 0) {
164 | | fl.log("MinCollateralUsd is 0");
165 | | }
166 | * | if (minCollateralUsd > 0 && minCollateralUsd <= 1e6) {
167 | | fl.log("MinCollateralUsd is between 0 and 1e6");
168 | | }
169 | * | if (minCollateralUsd > 1e6 && minCollateralUsd <= 1e12) {
170 | | fl.log("MinCollateralUsd is between 1e6 and 1e12");
171 | | }
172 | * | if (minCollateralUsd > 1e12 && minCollateralUsd <= 1e18) {
173 | | fl.log("MinCollateralUsd is between 1e12 and 1e18");
174 | | }
175 | * | if (minCollateralUsd > 1e18 && minCollateralUsd <= 1e24) {
176 | | fl.log("MinCollateralUsd is between 1e18 and 1e24");
177 | | }
178 | * | if (minCollateralUsd > 1e24) {
179 | * | fl.log("MinCollateralUsd is greater than 1e24");
180 | | }
181 | * | if (minCollateralUsd < 0 && minCollateralUsd >= -1e6) {
182 | | fl.log("MinCollateralUsd is between 0 and -1e6");
183 | | }
184 | * | if (minCollateralUsd < -1e6 && minCollateralUsd >= -1e12) {
185 | | fl.log("MinCollateralUsd is between -1e6 and -1e12");
186 | | }
187 | * | if (minCollateralUsd < -1e12 && minCollateralUsd >= -1e18) {
188 | | fl.log("MinCollateralUsd is between -1e12 and -1e18");
189 | | }
190 | * | if (minCollateralUsd < -1e18 && minCollateralUsd >= -1e24) {
191 | | fl.log("MinCollateralUsd is between -1e18 and -1e24");
192 | | }
193 | * | if (minCollateralUsd < -1e24) {
194 | | fl.log("MinCollateralUsd is less than -1e24");
195 | | }
196 | | }
197 | |
198 | * | function _logMinCollateralUsdForLeverageCoverage(
199 | | int256 minCollateralUsdForLeverage
200 | | ) internal {
201 | * | if (minCollateralUsdForLeverage == 0) {
202 | | fl.log("MinCollateralUsdForLeverage is 0");
203 | | }
204 | * | if (
205 | * | minCollateralUsdForLeverage > 0 &&
206 | * | minCollateralUsdForLeverage <= 1e6
207 | | ) {
208 | | fl.log("MinCollateralUsdForLeverage is between 0 and 1e6");
209 | | }
210 | * | if (
211 | * | minCollateralUsdForLeverage > 1e6 &&
212 | * | minCollateralUsdForLeverage <= 1e12
213 | | ) {
214 | | fl.log("MinCollateralUsdForLeverage is between 1e6 and 1e12");
215 | | }
216 | * | if (
217 | * | minCollateralUsdForLeverage > 1e12 &&
218 | * | minCollateralUsdForLeverage <= 1e18
219 | | ) {
220 | | fl.log("MinCollateralUsdForLeverage is between 1e12 and 1e18");
221 | | }
222 | * | if (
223 | * | minCollateralUsdForLeverage > 1e18 &&
224 | * | minCollateralUsdForLeverage <= 1e24
225 | | ) {
226 | | fl.log("MinCollateralUsdForLeverage is between 1e18 and 1e24");
227 | | }
228 | * | if (minCollateralUsdForLeverage > 1e24) {
229 | * | fl.log("MinCollateralUsdForLeverage is greater than 1e24");
230 | | }
231 | * | if (
232 | * | minCollateralUsdForLeverage < 0 &&
233 | | minCollateralUsdForLeverage >= -1e6
234 | | ) {
235 | | fl.log("MinCollateralUsdForLeverage is between 0 and -1e6");
236 | | }
237 | * | if (
238 | * | minCollateralUsdForLeverage < -1e6 &&
239 | | minCollateralUsdForLeverage >= -1e12
240 | | ) {
241 | | fl.log("MinCollateralUsdForLeverage is between -1e6 and -1e12");
242 | | }
243 | * | if (
244 | * | minCollateralUsdForLeverage < -1e12 &&
245 | | minCollateralUsdForLeverage >= -1e18
246 | | ) {
247 | | fl.log("MinCollateralUsdForLeverage is between -1e12 and -1e18");
248 | | }
249 | * | if (
250 | * | minCollateralUsdForLeverage < -1e18 &&
251 | | minCollateralUsdForLeverage >= -1e24
252 | | ) {
253 | | fl.log("MinCollateralUsdForLeverage is between -1e18 and -1e24");
254 | | }
255 | * | if (minCollateralUsdForLeverage < -1e24) {
256 | | fl.log("MinCollateralUsdForLeverage is less than -1e24");
257 | | }
258 | | }
259 | | }
260 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/PositionCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./positionCoverage/CreateOrderCoverage.sol";
6 | | import "./positionCoverage/CancelOrderCoverage.sol";
7 | | import "./positionCoverage/IncreasePositionInfoCoverage.sol";
8 | | import "./positionCoverage/IncreasePositionMarketCoverage.sol";
9 | | import "./positionCoverage/DecreasePositionInfoCoverage.sol";
10 | | import "./positionCoverage/DecreasePositionMarketCoverage.sol";
11 | |
12 | | contract PositionCoverage is
13 | | CreateOrderCoverage,
14 | | CancelOrderCoverage,
15 | | IncreasePositionInfoCoverage,
16 | | IncreasePositionMarketCoverage,
17 | | DecreasePositionInfoCoverage,
18 | | DecreasePositionMarketCoverage
19 | | {}
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/ShiftCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./shiftCoverage/ShiftCreatedCoverage.sol";
6 | | import "./shiftCoverage/ShiftCancelCoverage.sol";
7 | | import "./shiftCoverage/ShiftExecutedCoverage.sol";
8 | |
9 | | contract ShiftCoverage is ShiftCreatedCoverage, ShiftCancelCoverage, ShiftExecutedCoverage {}
10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/WithdrawalCoverage.sol
1 | | pragma solidity ^0.8.0;
2 | |
3 | | import "./withdrawalCoverage/WithdrawalCreatedCoverage.sol";
4 | | import "./withdrawalCoverage/WithdrawalCancelCoverage.sol";
5 | | import "./withdrawalCoverage/WithdrawalExecuteCoverage.sol";
6 | | import "./withdrawalCoverage/WithdrawalExecuteAtomicCoverage.sol";
7 | |
8 | | contract WithdrawalCoverage is
9 | | WithdrawalCreatedCoverage,
10 | | WithdrawalCancelCoverage,
11 | | WithdrawalExecuteCoverage,
12 | | WithdrawalExecuteAtomicCoverage
13 | | {}
14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/CancelOrderCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract CancelOrderCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ CANCEL ORDER COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | | function _checkOrderCancelCoverage(
14 | | OrderCreated memory orderToCancel
15 | | ) internal {
16 | | _logReceiverCoverage_cancelOrder(
17 | | orderToCancel.createOrderParams.addresses.receiver
18 | | );
19 | | _logCancellationReceiverCoverage_cancelOrder(
20 | | orderToCancel.createOrderParams.addresses.cancellationReceiver
21 | | );
22 | | _logCallbackContractCoverage_cancelOrder(
23 | | orderToCancel.createOrderParams.addresses.callbackContract
24 | | );
25 | | _logUiFeeReceiverCoverage_cancelOrder(
26 | | orderToCancel.createOrderParams.addresses.uiFeeReceiver
27 | | );
28 | | _logInitialCollateralTokenCoverage_cancelOrder(
29 | | orderToCancel.createOrderParams.addresses.initialCollateralToken
30 | | );
31 | | _logMarketCoverage_cancelOrder(
32 | | orderToCancel.createOrderParams.addresses.market
33 | | );
34 | | _logSwapPathCoverage_cancelOrder(
35 | | orderToCancel.createOrderParams.addresses.swapPath
36 | | );
37 | | _logOrderTypeCoverage_cancelOrder(
38 | | orderToCancel.createOrderParams.orderType
39 | | );
40 | | _logDecreasePositionSwapTypeCoverage_cancelOrder(
41 | | orderToCancel.createOrderParams.decreasePositionSwapType
42 | | );
43 | | _logIsLongCoverage_cancelOrder(orderToCancel.createOrderParams.isLong);
44 | | _logShouldUnwrapNativeTokenCoverage_cancelOrder(
45 | | orderToCancel.createOrderParams.shouldUnwrapNativeToken
46 | | );
47 | | _logAutoCancelCoverage_cancelOrder(
48 | | orderToCancel.createOrderParams.autoCancel
49 | | );
50 | | _logReferralCodeCoverage_cancelOrder(
51 | | orderToCancel.createOrderParams.referralCode
52 | | );
53 | | _logSizeDeltaUsdCoverage_cancelOrder(
54 | | orderToCancel.createOrderParams.numbers.sizeDeltaUsd
55 | | );
56 | | _logInitialCollateralDeltaAmountCoverage_cancelOrder(
57 | | orderToCancel.createOrderParams.numbers.initialCollateralDeltaAmount
58 | | );
59 | | _logTriggerPriceCoverage_cancelOrder(
60 | | orderToCancel.createOrderParams.numbers.triggerPrice
61 | | );
62 | | _logAcceptablePriceCoverage_cancelOrder(
63 | | orderToCancel.createOrderParams.numbers.acceptablePrice
64 | | );
65 | | _logExecutionFeeCoverage_cancelOrder(
66 | | orderToCancel.createOrderParams.numbers.executionFee
67 | | );
68 | | _logCallbackGasLimitCoverage_cancelOrder(
69 | | orderToCancel.createOrderParams.numbers.callbackGasLimit
70 | | );
71 | | _logMinOutputAmountCoverage_cancelOrder(
72 | | orderToCancel.createOrderParams.numbers.minOutputAmount
73 | | );
74 | | _logKeyCoverage_cancelOrder(orderToCancel.key);
75 | | _logUpdatedAtCoverage_cancelOrder(orderToCancel.updatedAt);
76 | | _logUserCoverage_cancelOrder(orderToCancel.user);
77 | | _logHandlerTypeCoverage_cancelOrder(orderToCancel.handlerType);
78 | | _logAmountSentCoverage_cancelOrder(orderToCancel.amountSent);
79 | | _logIsCloseCoverage_cancelOrder(orderToCancel.isClose);
80 | | }
81 | |
82 | | function _logReceiverCoverage_cancelOrder(address receiver) internal {
83 | | if (receiver == USER0) {
84 | | fl.log("Receiver USER0 hit");
85 | | }
86 | | if (receiver == USER1) {
87 | | fl.log("Receiver USER1 hit");
88 | | }
89 | | if (receiver == USER2) {
90 | | fl.log("Receiver USER2 hit");
91 | | }
92 | | if (receiver == USER3) {
93 | | fl.log("Receiver USER3 hit");
94 | | }
95 | | if (receiver == USER4) {
96 | | fl.log("Receiver USER4 hit");
97 | | }
98 | | if (receiver == USER5) {
99 | | fl.log("Receiver USER5 hit");
100 | | }
101 | | if (receiver == USER6) {
102 | | fl.log("Receiver USER6 hit");
103 | | }
104 | | if (receiver == USER7) {
105 | | fl.log("Receiver USER7 hit");
106 | | }
107 | | if (receiver == USER8) {
108 | | fl.log("Receiver USER8 hit");
109 | | }
110 | | if (receiver == USER9) {
111 | | fl.log("Receiver USER9 hit");
112 | | }
113 | | if (receiver == USER10) {
114 | | fl.log("Receiver USER10 hit");
115 | | }
116 | | if (receiver == USER11) {
117 | | fl.log("Receiver USER11 hit");
118 | | }
119 | | if (receiver == USER12) {
120 | | fl.log("Receiver USER12 hit");
121 | | }
122 | | if (receiver == USER13) {
123 | | fl.log("Receiver USER13 hit");
124 | | }
125 | | }
126 | |
127 | | function _logCancellationReceiverCoverage_cancelOrder(
128 | | address cancellationReceiver
129 | | ) internal {
130 | | if (cancellationReceiver == USER0) {
131 | | fl.log("CancellationReceiver USER0 hit");
132 | | }
133 | | if (cancellationReceiver == USER1) {
134 | | fl.log("CancellationReceiver USER1 hit");
135 | | }
136 | | if (cancellationReceiver == USER2) {
137 | | fl.log("CancellationReceiver USER2 hit");
138 | | }
139 | | if (cancellationReceiver == USER3) {
140 | | fl.log("CancellationReceiver USER3 hit");
141 | | }
142 | | if (cancellationReceiver == USER4) {
143 | | fl.log("CancellationReceiver USER4 hit");
144 | | }
145 | | if (cancellationReceiver == USER5) {
146 | | fl.log("CancellationReceiver USER5 hit");
147 | | }
148 | | if (cancellationReceiver == USER6) {
149 | | fl.log("CancellationReceiver USER6 hit");
150 | | }
151 | | if (cancellationReceiver == USER7) {
152 | | fl.log("CancellationReceiver USER7 hit");
153 | | }
154 | | if (cancellationReceiver == USER8) {
155 | | fl.log("CancellationReceiver USER8 hit");
156 | | }
157 | | if (cancellationReceiver == USER9) {
158 | | fl.log("CancellationReceiver USER9 hit");
159 | | }
160 | | if (cancellationReceiver == USER10) {
161 | | fl.log("CancellationReceiver USER10 hit");
162 | | }
163 | | if (cancellationReceiver == USER11) {
164 | | fl.log("CancellationReceiver USER11 hit");
165 | | }
166 | | if (cancellationReceiver == USER12) {
167 | | fl.log("CancellationReceiver USER12 hit");
168 | | }
169 | | if (cancellationReceiver == USER13) {
170 | | fl.log("CancellationReceiver USER13 hit");
171 | | }
172 | | }
173 | |
174 | | function _logCallbackContractCoverage_cancelOrder(
175 | | address callbackContract
176 | | ) internal {
177 | | if (callbackContract == address(0)) {
178 | | fl.log("CallbackContract is address(0)");
179 | | } else {
180 | | fl.log("CallbackContract is non-zero address");
181 | | }
182 | | }
183 | |
184 | | function _logUiFeeReceiverCoverage_cancelOrder(
185 | | address uiFeeReceiver
186 | | ) internal {
187 | | if (uiFeeReceiver == address(0)) {
188 | | fl.log("UiFeeReceiver is address(0)");
189 | | } else {
190 | | fl.log("UiFeeReceiver is non-zero address");
191 | | }
192 | | }
193 | |
194 | | function _logInitialCollateralTokenCoverage_cancelOrder(
195 | | address initialCollateralToken
196 | | ) internal {
197 | | if (initialCollateralToken == address(WETH)) {
198 | | fl.log("InitialCollateralToken is WETH");
199 | | }
200 | | if (initialCollateralToken == address(WBTC)) {
201 | | fl.log("InitialCollateralToken is WBTC");
202 | | }
203 | | if (initialCollateralToken == address(USDC)) {
204 | | fl.log("InitialCollateralToken is USDC");
205 | | }
206 | | if (initialCollateralToken == address(USDT)) {
207 | | fl.log("InitialCollateralToken is USDT");
208 | | }
209 | | if (initialCollateralToken == address(SOL)) {
210 | | fl.log("InitialCollateralToken is SOL");
211 | | }
212 | | }
213 | |
214 | | function _logMarketCoverage_cancelOrder(address market) internal {
215 | | if (market == address(market_0_WETH_USDC)) {
216 | | fl.log("Market market_0_WETH_USDC hit");
217 | | }
218 | |
219 | | if (market == address(market_WBTC_WBTC_USDC)) {
220 | | fl.log("Market market_WBTC_WBTC_USDC hit");
221 | | }
222 | | if (market == address(market_WETH_WETH_USDC)) {
223 | | fl.log("Market market_WETH_WETH_USDC hit");
224 | | }
225 | | if (market == address(market_WETH_WETH_USDT)) {
226 | | fl.log("Market market_WETH_WETH_USDT hit");
227 | | }
228 | | }
229 | |
230 | | function _logSwapPathCoverage_cancelOrder(
231 | | address[] memory swapPath
232 | | ) internal {
233 | | if (swapPath.length == 0) {
234 | | fl.log("SwapPath is empty");
235 | | }
236 | | if (swapPath.length == 1) {
237 | | fl.log("SwapPath has 1 element");
238 | | }
239 | | if (swapPath.length == 2) {
240 | | fl.log("SwapPath has 2 elements");
241 | | }
242 | | if (swapPath.length >= 3) {
243 | | fl.log("SwapPath has 3 or more elements");
244 | | }
245 | | }
246 | |
247 | | function _logOrderTypeCoverage_cancelOrder(
248 | | Order.OrderType orderType
249 | | ) internal {
250 | | if (orderType == Order.OrderType.MarketSwap) {
251 | | fl.log("OrderType is MarketSwap");
252 | | }
253 | | if (orderType == Order.OrderType.LimitSwap) {
254 | | fl.log("OrderType is LimitSwap");
255 | | }
256 | | if (orderType == Order.OrderType.MarketIncrease) {
257 | | fl.log("OrderType is MarketIncrease");
258 | | }
259 | | if (orderType == Order.OrderType.LimitIncrease) {
260 | | fl.log("OrderType is LimitIncrease");
261 | | }
262 | | if (orderType == Order.OrderType.MarketDecrease) {
263 | | fl.log("OrderType is MarketDecrease");
264 | | }
265 | | if (orderType == Order.OrderType.LimitDecrease) {
266 | | fl.log("OrderType is LimitDecrease");
267 | | }
268 | | if (orderType == Order.OrderType.StopLossDecrease) {
269 | | fl.log("OrderType is StopLossDecrease");
270 | | }
271 | | if (orderType == Order.OrderType.Liquidation) {
272 | | fl.log("OrderType is Liquidation");
273 | | }
274 | | }
275 | |
276 | | function _logDecreasePositionSwapTypeCoverage_cancelOrder(
277 | | Order.DecreasePositionSwapType decreasePositionSwapType
278 | | ) internal {
279 | | if (decreasePositionSwapType == Order.DecreasePositionSwapType.NoSwap) {
280 | | fl.log("DecreasePositionSwapType is NoSwap");
281 | | }
282 | | if (
283 | | decreasePositionSwapType ==
284 | | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken
285 | | ) {
286 | | fl.log("DecreasePositionSwapType is SwapPnlTokenToCollateralToken");
287 | | }
288 | | if (
289 | | decreasePositionSwapType ==
290 | | Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken
291 | | ) {
292 | | fl.log("DecreasePositionSwapType is SwapCollateralTokenToPnlToken");
293 | | }
294 | | }
295 | |
296 | | function _logIsLongCoverage_cancelOrder(bool isLong) internal {
297 | | if (isLong) {
298 | | fl.log("IsLong is true");
299 | | } else {
300 | | fl.log("IsLong is false");
301 | | }
302 | | }
303 | |
304 | | function _logShouldUnwrapNativeTokenCoverage_cancelOrder(
305 | | bool shouldUnwrapNativeToken
306 | | ) internal {
307 | | if (shouldUnwrapNativeToken) {
308 | | fl.log("ShouldUnwrapNativeToken is true");
309 | | } else {
310 | | fl.log("ShouldUnwrapNativeToken is false");
311 | | }
312 | | }
313 | |
314 | | function _logAutoCancelCoverage_cancelOrder(bool autoCancel) internal {
315 | | if (autoCancel) {
316 | | fl.log("AutoCancel is true");
317 | | } else {
318 | | fl.log("AutoCancel is false");
319 | | }
320 | | }
321 | |
322 | | function _logReferralCodeCoverage_cancelOrder(
323 | | bytes32 referralCode
324 | | ) internal {
325 | | if (referralCode == bytes32(0)) {
326 | | fl.log("ReferralCode is empty");
327 | | } else {
328 | | fl.log("ReferralCode is non-empty");
329 | | }
330 | | }
331 | |
332 | | function _logSizeDeltaUsdCoverage_cancelOrder(
333 | | uint256 sizeDeltaUsd
334 | | ) internal {
335 | | if (sizeDeltaUsd == 0) {
336 | | fl.log("SizeDeltaUsd is 0");
337 | | }
338 | | if (sizeDeltaUsd > 0 && sizeDeltaUsd <= 1e6) {
339 | | fl.log("SizeDeltaUsd is between 0 and 1e6");
340 | | }
341 | | if (sizeDeltaUsd > 1e6 && sizeDeltaUsd <= 1e12) {
342 | | fl.log("SizeDeltaUsd is between 1e6 and 1e12");
343 | | }
344 | | if (sizeDeltaUsd > 1e12 && sizeDeltaUsd <= 1e18) {
345 | | fl.log("SizeDeltaUsd is between 1e12 and 1e18");
346 | | }
347 | | if (sizeDeltaUsd > 1e18 && sizeDeltaUsd <= 1e24) {
348 | | fl.log("SizeDeltaUsd is between 1e18 and 1e24");
349 | | }
350 | | if (sizeDeltaUsd > 1e24) {
351 | | fl.log("SizeDeltaUsd is greater than 1e24");
352 | | }
353 | | }
354 | |
355 | | function _logInitialCollateralDeltaAmountCoverage_cancelOrder(
356 | | uint256 initialCollateralDeltaAmount
357 | | ) internal {
358 | | if (initialCollateralDeltaAmount == 0) {
359 | | fl.log("InitialCollateralDeltaAmount is 0");
360 | | }
361 | | if (
362 | | initialCollateralDeltaAmount > 0 &&
363 | | initialCollateralDeltaAmount <= 1e6
364 | | ) {
365 | | fl.log("InitialCollateralDeltaAmount is between 0 and 1e6");
366 | | }
367 | | if (
368 | | initialCollateralDeltaAmount > 1e6 &&
369 | | initialCollateralDeltaAmount <= 1e12
370 | | ) {
371 | | fl.log("InitialCollateralDeltaAmount is between 1e6 and 1e12");
372 | | }
373 | | if (
374 | | initialCollateralDeltaAmount > 1e12 &&
375 | | initialCollateralDeltaAmount <= 1e18
376 | | ) {
377 | | fl.log("InitialCollateralDeltaAmount is between 1e12 and 1e18");
378 | | }
379 | | if (
380 | | initialCollateralDeltaAmount > 1e18 &&
381 | | initialCollateralDeltaAmount <= 1e24
382 | | ) {
383 | | fl.log("InitialCollateralDeltaAmount is between 1e18 and 1e24");
384 | | }
385 | | if (initialCollateralDeltaAmount > 1e24) {
386 | | fl.log("InitialCollateralDeltaAmount is greater than 1e24");
387 | | }
388 | | }
389 | |
390 | | function _logTriggerPriceCoverage_cancelOrder(
391 | | uint256 triggerPrice
392 | | ) internal {
393 | | if (triggerPrice == 0) {
394 | | fl.log("TriggerPrice is 0");
395 | | }
396 | | if (triggerPrice > 0 && triggerPrice <= 1e6) {
397 | | fl.log("TriggerPrice is between 0 and 1e6");
398 | | }
399 | | if (triggerPrice > 1e6 && triggerPrice <= 1e12) {
400 | | fl.log("TriggerPrice is between 1e6 and 1e12");
401 | | }
402 | | if (triggerPrice > 1e12 && triggerPrice <= 1e18) {
403 | | fl.log("TriggerPrice is between 1e12 and 1e18");
404 | | }
405 | | if (triggerPrice > 1e18 && triggerPrice <= 1e24) {
406 | | fl.log("TriggerPrice is between 1e18 and 1e24");
407 | | }
408 | | if (triggerPrice > 1e24) {
409 | | fl.log("TriggerPrice is greater than 1e24");
410 | | }
411 | | }
412 | |
413 | | function _logAcceptablePriceCoverage_cancelOrder(
414 | | uint256 acceptablePrice
415 | | ) internal {
416 | | if (acceptablePrice == 0) {
417 | | fl.log("AcceptablePrice is 0");
418 | | }
419 | | if (acceptablePrice > 0 && acceptablePrice <= 1e6) {
420 | | fl.log("AcceptablePrice is between 0 and 1e6");
421 | | }
422 | | if (acceptablePrice > 1e6 && acceptablePrice <= 1e12) {
423 | | fl.log("AcceptablePrice is between 1e6 and 1e12");
424 | | }
425 | | if (acceptablePrice > 1e12 && acceptablePrice <= 1e18) {
426 | | fl.log("AcceptablePrice is between 1e12 and 1e18");
427 | | }
428 | | if (acceptablePrice > 1e18 && acceptablePrice <= 1e24) {
429 | | fl.log("AcceptablePrice is between 1e18 and 1e24");
430 | | }
431 | | if (acceptablePrice > 1e24) {
432 | | fl.log("AcceptablePrice is greater than 1e24");
433 | | }
434 | | }
435 | |
436 | | function _logExecutionFeeCoverage_cancelOrder(
437 | | uint256 executionFee
438 | | ) internal {
439 | | if (executionFee == 0) {
440 | | fl.log("ExecutionFee is 0");
441 | | }
442 | | if (executionFee > 0 && executionFee <= 1e6) {
443 | | fl.log("ExecutionFee is between 0 and 1e6");
444 | | }
445 | | if (executionFee > 1e6 && executionFee <= 1e12) {
446 | | fl.log("ExecutionFee is between 1e6 and 1e12");
447 | | }
448 | | if (executionFee > 1e12 && executionFee <= 1e18) {
449 | | fl.log("ExecutionFee is between 1e12 and 1e18");
450 | | }
451 | | if (executionFee > 1e18 && executionFee <= 1e24) {
452 | | fl.log("ExecutionFee is between 1e18 and 1e24");
453 | | }
454 | | if (executionFee > 1e24) {
455 | | fl.log("ExecutionFee is greater than 1e24");
456 | | }
457 | | }
458 | |
459 | | function _logCallbackGasLimitCoverage_cancelOrder(
460 | | uint256 callbackGasLimit
461 | | ) internal {
462 | | if (callbackGasLimit == 0) {
463 | | fl.log("CallbackGasLimit is 0");
464 | | }
465 | | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
466 | | fl.log("CallbackGasLimit is between 0 and 1e6");
467 | | }
468 | | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
469 | | fl.log("CallbackGasLimit is between 1e6 and 1e12");
470 | | }
471 | | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
472 | | fl.log("CallbackGasLimit is between 1e12 and 1e18");
473 | | }
474 | | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
475 | | fl.log("CallbackGasLimit is between 1e18 and 1e24");
476 | | }
477 | | if (callbackGasLimit > 1e24) {
478 | | fl.log("CallbackGasLimit is greater than 1e24");
479 | | }
480 | | }
481 | |
482 | | function _logMinOutputAmountCoverage_cancelOrder(
483 | | uint256 minOutputAmount
484 | | ) internal {
485 | | if (minOutputAmount == 0) {
486 | | fl.log("MinOutputAmount is 0");
487 | | }
488 | | if (minOutputAmount > 0 && minOutputAmount <= 1e6) {
489 | | fl.log("MinOutputAmount is between 0 and 1e6");
490 | | }
491 | | if (minOutputAmount > 1e6 && minOutputAmount <= 1e12) {
492 | | fl.log("MinOutputAmount is between 1e6 and 1e12");
493 | | }
494 | | if (minOutputAmount > 1e12 && minOutputAmount <= 1e18) {
495 | | fl.log("MinOutputAmount is between 1e12 and 1e18");
496 | | }
497 | | if (minOutputAmount > 1e18 && minOutputAmount <= 1e24) {
498 | | fl.log("MinOutputAmount is between 1e18 and 1e24");
499 | | }
500 | | if (minOutputAmount > 1e24) {
501 | | fl.log("MinOutputAmount is greater than 1e24");
502 | | }
503 | | }
504 | |
505 | | function _logKeyCoverage_cancelOrder(bytes32 key) internal {
506 | | if (key == bytes32(0)) {
507 | | fl.log("Key is empty");
508 | | } else {
509 | | fl.log("Key is non-empty");
510 | | }
511 | | }
512 | |
513 | | function _logUpdatedAtCoverage_cancelOrder(uint256 updatedAt) internal {
514 | | if (updatedAt == 0) {
515 | | fl.log("UpdatedAt is 0");
516 | | } else {
517 | | fl.log("UpdatedAt is non-zero");
518 | | }
519 | | }
520 | |
521 | | function _logUserCoverage_cancelOrder(address user) internal {
522 | | if (user == USER0) {
523 | | fl.log("User USER0 hit");
524 | | }
525 | | if (user == USER1) {
526 | | fl.log("User USER1 hit");
527 | | }
528 | | if (user == USER2) {
529 | | fl.log("User USER2 hit");
530 | | }
531 | | if (user == USER3) {
532 | | fl.log("User USER3 hit");
533 | | }
534 | | if (user == USER4) {
535 | | fl.log("User USER4 hit");
536 | | }
537 | | if (user == USER5) {
538 | | fl.log("User USER5 hit");
539 | | }
540 | | if (user == USER6) {
541 | | fl.log("User USER6 hit");
542 | | }
543 | | if (user == USER7) {
544 | | fl.log("User USER7 hit");
545 | | }
546 | | if (user == USER8) {
547 | | fl.log("User USER8 hit");
548 | | }
549 | | if (user == USER9) {
550 | | fl.log("User USER9 hit");
551 | | }
552 | | if (user == USER10) {
553 | | fl.log("User USER10 hit");
554 | | }
555 | | if (user == USER11) {
556 | | fl.log("User USER11 hit");
557 | | }
558 | | if (user == USER12) {
559 | | fl.log("User USER12 hit");
560 | | }
561 | | if (user == USER13) {
562 | | fl.log("User USER13 hit");
563 | | }
564 | | }
565 | |
566 | | function _logHandlerTypeCoverage_cancelOrder(bytes32 handlerType) internal {
567 | | if (handlerType == bytes32(0)) {
568 | | fl.log("HandlerType is empty");
569 | | } else {
570 | | fl.log("HandlerType is non-empty");
571 | | }
572 | | }
573 | |
574 | | function _logAmountSentCoverage_cancelOrder(uint256 amountSent) internal {
575 | | if (amountSent == 0) {
576 | | fl.log("AmountSent is 0");
577 | | }
578 | | if (amountSent > 0 && amountSent <= 1e6) {
579 | | fl.log("AmountSent is between 0 and 1e6");
580 | | }
581 | | if (amountSent > 1e6 && amountSent <= 1e12) {
582 | | fl.log("AmountSent is between 1e6 and 1e12");
583 | | }
584 | | if (amountSent > 1e12 && amountSent <= 1e18) {
585 | | fl.log("AmountSent is between 1e12 and 1e18");
586 | | }
587 | | if (amountSent > 1e18 && amountSent <= 1e24) {
588 | | fl.log("AmountSent is between 1e18 and 1e24");
589 | | }
590 | | if (amountSent > 1e24) {
591 | | fl.log("AmountSent is greater than 1e24");
592 | | }
593 | | }
594 | |
595 | | function _logIsCloseCoverage_cancelOrder(bool isClose) internal {
596 | | if (isClose) {
597 | | fl.log("IsClose is true");
598 | | } else {
599 | | fl.log("IsClose is false");
600 | | }
601 | | }
602 | | }
603 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/CreateOrderCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract CreateOrderCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ CREATE ORDER COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | * | function _checkOrderCreatedCoverage(
14 | | OrderCreated memory orderCreated
15 | | ) internal {
16 | * | _logReceiverCoverage(orderCreated.createOrderParams.addresses.receiver);
17 | * | _logCancellationReceiverCoverage(
18 | * | orderCreated.createOrderParams.addresses.cancellationReceiver
19 | | );
20 | * | _logCallbackContractCoverage(
21 | * | orderCreated.createOrderParams.addresses.callbackContract
22 | | );
23 | * | _logUiFeeReceiverCoverage(
24 | * | orderCreated.createOrderParams.addresses.uiFeeReceiver
25 | | );
26 | * | _logInitialCollateralTokenCoverage(
27 | * | orderCreated.createOrderParams.addresses.initialCollateralToken
28 | | );
29 | * | _logMarketCoverage(orderCreated.createOrderParams.addresses.market);
30 | * | _logSwapPathCoverage(orderCreated.createOrderParams.addresses.swapPath);
31 | * | _logOrderTypeCoverage(orderCreated.createOrderParams.orderType);
32 | * | _logDecreasePositionSwapTypeCoverage(
33 | * | orderCreated.createOrderParams.decreasePositionSwapType
34 | | );
35 | * | _logIsLongCoverage(orderCreated.createOrderParams.isLong);
36 | * | _logShouldUnwrapNativeTokenCoverage(
37 | * | orderCreated.createOrderParams.shouldUnwrapNativeToken
38 | | );
39 | * | _logAutoCancelCoverage(orderCreated.createOrderParams.autoCancel);
40 | * | _logReferralCodeCoverage(orderCreated.createOrderParams.referralCode);
41 | * | _logSizeDeltaUsdCoverage(
42 | * | orderCreated.createOrderParams.numbers.sizeDeltaUsd
43 | | );
44 | * | _logInitialCollateralDeltaAmountCoverage(
45 | * | orderCreated.createOrderParams.numbers.initialCollateralDeltaAmount
46 | | );
47 | * | _logTriggerPriceCoverage(
48 | * | orderCreated.createOrderParams.numbers.triggerPrice
49 | | );
50 | * | _logAcceptablePriceCoverage(
51 | * | orderCreated.createOrderParams.numbers.acceptablePrice
52 | | );
53 | * | _logExecutionFeeCoverage(
54 | * | orderCreated.createOrderParams.numbers.executionFee
55 | | );
56 | * | _logCallbackGasLimitCoverage(
57 | * | orderCreated.createOrderParams.numbers.callbackGasLimit
58 | | );
59 | * | _logMinOutputAmountCoverage(
60 | * | orderCreated.createOrderParams.numbers.minOutputAmount
61 | | );
62 | * | _logKeyCoverage(orderCreated.key);
63 | * | _logUpdatedAtCoverage(orderCreated.updatedAt);
64 | * | _logUserCoverage(orderCreated.user);
65 | * | _logHandlerTypeCoverage(orderCreated.handlerType);
66 | * | _logAmountSentCoverage(orderCreated.amountSent);
67 | * | _logIsCloseCoverage(orderCreated.isClose);
68 | | }
69 | |
70 | * | function _logReceiverCoverage(address receiver) internal {
71 | * | if (receiver == USER0) {
72 | * | fl.log("Receiver USER0 hit");
73 | | }
74 | * | if (receiver == USER1) {
75 | * | fl.log("Receiver USER1 hit");
76 | | }
77 | * | if (receiver == USER2) {
78 | * | fl.log("Receiver USER2 hit");
79 | | }
80 | * | if (receiver == USER3) {
81 | * | fl.log("Receiver USER3 hit");
82 | | }
83 | * | if (receiver == USER4) {
84 | * | fl.log("Receiver USER4 hit");
85 | | }
86 | * | if (receiver == USER5) {
87 | * | fl.log("Receiver USER5 hit");
88 | | }
89 | * | if (receiver == USER6) {
90 | * | fl.log("Receiver USER6 hit");
91 | | }
92 | * | if (receiver == USER7) {
93 | * | fl.log("Receiver USER7 hit");
94 | | }
95 | * | if (receiver == USER8) {
96 | * | fl.log("Receiver USER8 hit");
97 | | }
98 | * | if (receiver == USER9) {
99 | * | fl.log("Receiver USER9 hit");
100 | | }
101 | * | if (receiver == USER10) {
102 | * | fl.log("Receiver USER10 hit");
103 | | }
104 | * | if (receiver == USER11) {
105 | * | fl.log("Receiver USER11 hit");
106 | | }
107 | * | if (receiver == USER12) {
108 | * | fl.log("Receiver USER12 hit");
109 | | }
110 | * | if (receiver == USER13) {
111 | * | fl.log("Receiver USER13 hit");
112 | | }
113 | | }
114 | |
115 | * | function _logCancellationReceiverCoverage(
116 | | address cancellationReceiver
117 | | ) internal {
118 | * | if (cancellationReceiver == USER0) {
119 | * | fl.log("CancellationReceiver USER0 hit");
120 | | }
121 | * | if (cancellationReceiver == USER1) {
122 | * | fl.log("CancellationReceiver USER1 hit");
123 | | }
124 | * | if (cancellationReceiver == USER2) {
125 | * | fl.log("CancellationReceiver USER2 hit");
126 | | }
127 | * | if (cancellationReceiver == USER3) {
128 | * | fl.log("CancellationReceiver USER3 hit");
129 | | }
130 | * | if (cancellationReceiver == USER4) {
131 | * | fl.log("CancellationReceiver USER4 hit");
132 | | }
133 | * | if (cancellationReceiver == USER5) {
134 | * | fl.log("CancellationReceiver USER5 hit");
135 | | }
136 | * | if (cancellationReceiver == USER6) {
137 | * | fl.log("CancellationReceiver USER6 hit");
138 | | }
139 | * | if (cancellationReceiver == USER7) {
140 | * | fl.log("CancellationReceiver USER7 hit");
141 | | }
142 | * | if (cancellationReceiver == USER8) {
143 | * | fl.log("CancellationReceiver USER8 hit");
144 | | }
145 | * | if (cancellationReceiver == USER9) {
146 | * | fl.log("CancellationReceiver USER9 hit");
147 | | }
148 | * | if (cancellationReceiver == USER10) {
149 | * | fl.log("CancellationReceiver USER10 hit");
150 | | }
151 | * | if (cancellationReceiver == USER11) {
152 | * | fl.log("CancellationReceiver USER11 hit");
153 | | }
154 | * | if (cancellationReceiver == USER12) {
155 | * | fl.log("CancellationReceiver USER12 hit");
156 | | }
157 | * | if (cancellationReceiver == USER13) {
158 | * | fl.log("CancellationReceiver USER13 hit");
159 | | }
160 | | }
161 | |
162 | * | function _logCallbackContractCoverage(address callbackContract) internal {
163 | * | if (callbackContract == address(0)) {
164 | | fl.log("CallbackContract is address(0)");
165 | | } else {
166 | * | fl.log("CallbackContract is non-zero address");
167 | | }
168 | | }
169 | |
170 | * | function _logUiFeeReceiverCoverage(address uiFeeReceiver) internal {
171 | * | if (uiFeeReceiver == address(0)) {
172 | * | fl.log("UiFeeReceiver is address(0)");
173 | | } else {
174 | | fl.log("UiFeeReceiver is non-zero address");
175 | | }
176 | | }
177 | |
178 | * | function _logInitialCollateralTokenCoverage(
179 | | address initialCollateralToken
180 | | ) internal {
181 | * | if (initialCollateralToken == address(WETH)) {
182 | * | fl.log("InitialCollateralToken is WETH");
183 | | }
184 | * | if (initialCollateralToken == address(WBTC)) {
185 | * | fl.log("InitialCollateralToken is WBTC");
186 | | }
187 | * | if (initialCollateralToken == address(USDC)) {
188 | * | fl.log("InitialCollateralToken is USDC");
189 | | }
190 | * | if (initialCollateralToken == address(USDT)) {
191 | * | fl.log("InitialCollateralToken is USDT");
192 | | }
193 | * | if (initialCollateralToken == address(SOL)) {
194 | | fl.log("InitialCollateralToken is SOL");
195 | | }
196 | | }
197 | |
198 | * | function _logMarketCoverage(address market) internal {
199 | * | if (market == address(market_0_WETH_USDC)) {
200 | | fl.log("Market market_0_WETH_USDC hit");
201 | | }
202 | |
203 | * | if (market == address(market_WBTC_WBTC_USDC)) {
204 | * | fl.log("Market market_WBTC_WBTC_USDC hit");
205 | | }
206 | * | if (market == address(market_WETH_WETH_USDC)) {
207 | * | fl.log("Market market_WETH_WETH_USDC hit");
208 | | }
209 | * | if (market == address(market_WETH_WETH_USDT)) {
210 | * | fl.log("Market market_WETH_WETH_USDT hit");
211 | | }
212 | | }
213 | |
214 | * | function _logSwapPathCoverage(address[] memory swapPath) internal {
215 | * | if (swapPath.length == 0) {
216 | * | fl.log("SwapPath is empty");
217 | | }
218 | * | if (swapPath.length == 1) {
219 | * | fl.log("SwapPath has 1 element");
220 | | }
221 | * | if (swapPath.length == 2) {
222 | * | fl.log("SwapPath has 2 elements");
223 | | }
224 | * | if (swapPath.length >= 3) {
225 | * | fl.log("SwapPath has 3 or more elements");
226 | | }
227 | | }
228 | |
229 | * | function _logOrderTypeCoverage(Order.OrderType orderType) internal {
230 | * | if (orderType == Order.OrderType.MarketSwap) {
231 | * | fl.log("OrderType is MarketSwap");
232 | | }
233 | * | if (orderType == Order.OrderType.LimitSwap) {
234 | * | fl.log("OrderType is LimitSwap");
235 | | }
236 | * | if (orderType == Order.OrderType.MarketIncrease) {
237 | * | fl.log("OrderType is MarketIncrease");
238 | | }
239 | * | if (orderType == Order.OrderType.LimitIncrease) {
240 | * | fl.log("OrderType is LimitIncrease");
241 | | }
242 | * | if (orderType == Order.OrderType.MarketDecrease) {
243 | | fl.log("OrderType is MarketDecrease");
244 | | }
245 | * | if (orderType == Order.OrderType.LimitDecrease) {
246 | | fl.log("OrderType is LimitDecrease");
247 | | }
248 | * | if (orderType == Order.OrderType.StopLossDecrease) {
249 | * | fl.log("OrderType is StopLossDecrease");
250 | | }
251 | * | if (orderType == Order.OrderType.Liquidation) {
252 | | fl.log("OrderType is Liquidation");
253 | | }
254 | | }
255 | |
256 | * | function _logDecreasePositionSwapTypeCoverage(
257 | | Order.DecreasePositionSwapType decreasePositionSwapType
258 | | ) internal {
259 | * | if (decreasePositionSwapType == Order.DecreasePositionSwapType.NoSwap) {
260 | * | fl.log("DecreasePositionSwapType is NoSwap");
261 | | }
262 | * | if (
263 | * | decreasePositionSwapType ==
264 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken
265 | | ) {
266 | | fl.log("DecreasePositionSwapType is SwapPnlTokenToCollateralToken");
267 | | }
268 | * | if (
269 | * | decreasePositionSwapType ==
270 | * | Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken
271 | | ) {
272 | | fl.log("DecreasePositionSwapType is SwapCollateralTokenToPnlToken");
273 | | }
274 | | }
275 | |
276 | * | function _logIsLongCoverage(bool isLong) internal {
277 | * | if (isLong) {
278 | * | fl.log("IsLong is true");
279 | | } else {
280 | * | fl.log("IsLong is false");
281 | | }
282 | | }
283 | |
284 | * | function _logShouldUnwrapNativeTokenCoverage(
285 | | bool shouldUnwrapNativeToken
286 | | ) internal {
287 | * | if (shouldUnwrapNativeToken) {
288 | | fl.log("ShouldUnwrapNativeToken is true");
289 | | } else {
290 | * | fl.log("ShouldUnwrapNativeToken is false");
291 | | }
292 | | }
293 | |
294 | * | function _logAutoCancelCoverage(bool autoCancel) internal {
295 | * | if (autoCancel) {
296 | * | fl.log("AutoCancel is true");
297 | | } else {
298 | | fl.log("AutoCancel is false");
299 | | }
300 | | }
301 | |
302 | * | function _logReferralCodeCoverage(bytes32 referralCode) internal {
303 | * | if (referralCode == bytes32(0)) {
304 | * | fl.log("ReferralCode is empty");
305 | | } else {
306 | | fl.log("ReferralCode is non-empty");
307 | | }
308 | | }
309 | |
310 | * | function _logSizeDeltaUsdCoverage(uint256 sizeDeltaUsd) internal {
311 | * | if (sizeDeltaUsd == 0) {
312 | | fl.log("SizeDeltaUsd is 0");
313 | | }
314 | * | if (sizeDeltaUsd > 0 && sizeDeltaUsd <= 1e6) {
315 | | fl.log("SizeDeltaUsd is between 0 and 1e6");
316 | | }
317 | * | if (sizeDeltaUsd > 1e6 && sizeDeltaUsd <= 1e12) {
318 | | fl.log("SizeDeltaUsd is between 1e6 and 1e12");
319 | | }
320 | * | if (sizeDeltaUsd > 1e12 && sizeDeltaUsd <= 1e18) {
321 | | fl.log("SizeDeltaUsd is between 1e12 and 1e18");
322 | | }
323 | * | if (sizeDeltaUsd > 1e18 && sizeDeltaUsd <= 1e24) {
324 | | fl.log("SizeDeltaUsd is between 1e18 and 1e24");
325 | | }
326 | * | if (sizeDeltaUsd > 1e24) {
327 | * | fl.log("SizeDeltaUsd is greater than 1e24");
328 | | }
329 | | }
330 | |
331 | * | function _logInitialCollateralDeltaAmountCoverage(
332 | | uint256 initialCollateralDeltaAmount
333 | | ) internal {
334 | * | if (initialCollateralDeltaAmount == 0) {
335 | * | fl.log("InitialCollateralDeltaAmount is 0");
336 | | }
337 | * | if (
338 | * | initialCollateralDeltaAmount > 0 &&
339 | * | initialCollateralDeltaAmount <= 1e6
340 | | ) {
341 | * | fl.log("InitialCollateralDeltaAmount is between 0 and 1e6");
342 | | }
343 | * | if (
344 | * | initialCollateralDeltaAmount > 1e6 &&
345 | * | initialCollateralDeltaAmount <= 1e12
346 | | ) {
347 | * | fl.log("InitialCollateralDeltaAmount is between 1e6 and 1e12");
348 | | }
349 | * | if (
350 | * | initialCollateralDeltaAmount > 1e12 &&
351 | * | initialCollateralDeltaAmount <= 1e18
352 | | ) {
353 | * | fl.log("InitialCollateralDeltaAmount is between 1e12 and 1e18");
354 | | }
355 | * | if (
356 | * | initialCollateralDeltaAmount > 1e18 &&
357 | * | initialCollateralDeltaAmount <= 1e24
358 | | ) {
359 | * | fl.log("InitialCollateralDeltaAmount is between 1e18 and 1e24");
360 | | }
361 | * | if (initialCollateralDeltaAmount > 1e24) {
362 | | fl.log("InitialCollateralDeltaAmount is greater than 1e24");
363 | | }
364 | | }
365 | |
366 | * | function _logTriggerPriceCoverage(uint256 triggerPrice) internal {
367 | * | if (triggerPrice == 0) {
368 | | fl.log("TriggerPrice is 0");
369 | | }
370 | * | if (triggerPrice > 0 && triggerPrice <= 1e6) {
371 | | fl.log("TriggerPrice is between 0 and 1e6");
372 | | }
373 | * | if (triggerPrice > 1e6 && triggerPrice <= 1e12) {
374 | | fl.log("TriggerPrice is between 1e6 and 1e12");
375 | | }
376 | * | if (triggerPrice > 1e12 && triggerPrice <= 1e18) {
377 | * | fl.log("TriggerPrice is between 1e12 and 1e18");
378 | | }
379 | * | if (triggerPrice > 1e18 && triggerPrice <= 1e24) {
380 | * | fl.log("TriggerPrice is between 1e18 and 1e24");
381 | | }
382 | * | if (triggerPrice > 1e24) {
383 | * | fl.log("TriggerPrice is greater than 1e24");
384 | | }
385 | | }
386 | |
387 | * | function _logAcceptablePriceCoverage(uint256 acceptablePrice) internal {
388 | * | if (acceptablePrice == 0) {
389 | * | fl.log("AcceptablePrice is 0");
390 | | }
391 | * | if (acceptablePrice > 0 && acceptablePrice <= 1e6) {
392 | * | fl.log("AcceptablePrice is between 0 and 1e6");
393 | | }
394 | * | if (acceptablePrice > 1e6 && acceptablePrice <= 1e12) {
395 | | fl.log("AcceptablePrice is between 1e6 and 1e12");
396 | | }
397 | * | if (acceptablePrice > 1e12 && acceptablePrice <= 1e18) {
398 | | fl.log("AcceptablePrice is between 1e12 and 1e18");
399 | | }
400 | * | if (acceptablePrice > 1e18 && acceptablePrice <= 1e24) {
401 | | fl.log("AcceptablePrice is between 1e18 and 1e24");
402 | | }
403 | * | if (acceptablePrice > 1e24) {
404 | * | fl.log("AcceptablePrice is greater than 1e24");
405 | | }
406 | | }
407 | |
408 | * | function _logExecutionFeeCoverage(uint256 executionFee) internal {
409 | * | if (executionFee == 0) {
410 | * | fl.log("ExecutionFee is 0");
411 | | }
412 | * | if (executionFee > 0 && executionFee <= 1e6) {
413 | | fl.log("ExecutionFee is between 0 and 1e6");
414 | | }
415 | * | if (executionFee > 1e6 && executionFee <= 1e12) {
416 | * | fl.log("ExecutionFee is between 1e6 and 1e12");
417 | | }
418 | * | if (executionFee > 1e12 && executionFee <= 1e18) {
419 | | fl.log("ExecutionFee is between 1e12 and 1e18");
420 | | }
421 | * | if (executionFee > 1e18 && executionFee <= 1e24) {
422 | | fl.log("ExecutionFee is between 1e18 and 1e24");
423 | | }
424 | * | if (executionFee > 1e24) {
425 | | fl.log("ExecutionFee is greater than 1e24");
426 | | }
427 | | }
428 | |
429 | * | function _logCallbackGasLimitCoverage(uint256 callbackGasLimit) internal {
430 | * | if (callbackGasLimit == 0) {
431 | | fl.log("CallbackGasLimit is 0");
432 | | }
433 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
434 | * | fl.log("CallbackGasLimit is between 0 and 1e6");
435 | | }
436 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
437 | | fl.log("CallbackGasLimit is between 1e6 and 1e12");
438 | | }
439 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
440 | | fl.log("CallbackGasLimit is between 1e12 and 1e18");
441 | | }
442 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
443 | | fl.log("CallbackGasLimit is between 1e18 and 1e24");
444 | | }
445 | * | if (callbackGasLimit > 1e24) {
446 | | fl.log("CallbackGasLimit is greater than 1e24");
447 | | }
448 | | }
449 | |
450 | * | function _logMinOutputAmountCoverage(uint256 minOutputAmount) internal {
451 | * | if (minOutputAmount == 0) {
452 | | fl.log("MinOutputAmount is 0");
453 | | }
454 | * | if (minOutputAmount > 0 && minOutputAmount <= 1e6) {
455 | * | fl.log("MinOutputAmount is between 0 and 1e6");
456 | | }
457 | * | if (minOutputAmount > 1e6 && minOutputAmount <= 1e12) {
458 | | fl.log("MinOutputAmount is between 1e6 and 1e12");
459 | | }
460 | * | if (minOutputAmount > 1e12 && minOutputAmount <= 1e18) {
461 | | fl.log("MinOutputAmount is between 1e12 and 1e18");
462 | | }
463 | * | if (minOutputAmount > 1e18 && minOutputAmount <= 1e24) {
464 | | fl.log("MinOutputAmount is between 1e18 and 1e24");
465 | | }
466 | * | if (minOutputAmount > 1e24) {
467 | | fl.log("MinOutputAmount is greater than 1e24");
468 | | }
469 | | }
470 | |
471 | * | function _logKeyCoverage(bytes32 key) internal {
472 | * | if (key == bytes32(0)) {
473 | | fl.log("Key is empty");
474 | | } else {
475 | * | fl.log("Key is non-empty");
476 | | }
477 | | }
478 | |
479 | * | function _logUpdatedAtCoverage(uint256 updatedAt) internal {
480 | * | if (updatedAt == 0) {
481 | | fl.log("UpdatedAt is 0");
482 | | } else {
483 | * | fl.log("UpdatedAt is non-zero");
484 | | }
485 | | }
486 | |
487 | * | function _logUserCoverage(address user) internal {
488 | * | if (user == USER0) {
489 | * | fl.log("User USER0 hit");
490 | | }
491 | * | if (user == USER1) {
492 | * | fl.log("User USER1 hit");
493 | | }
494 | * | if (user == USER2) {
495 | * | fl.log("User USER2 hit");
496 | | }
497 | * | if (user == USER3) {
498 | * | fl.log("User USER3 hit");
499 | | }
500 | * | if (user == USER4) {
501 | * | fl.log("User USER4 hit");
502 | | }
503 | * | if (user == USER5) {
504 | * | fl.log("User USER5 hit");
505 | | }
506 | * | if (user == USER6) {
507 | * | fl.log("User USER6 hit");
508 | | }
509 | * | if (user == USER7) {
510 | * | fl.log("User USER7 hit");
511 | | }
512 | * | if (user == USER8) {
513 | * | fl.log("User USER8 hit");
514 | | }
515 | * | if (user == USER9) {
516 | * | fl.log("User USER9 hit");
517 | | }
518 | * | if (user == USER10) {
519 | * | fl.log("User USER10 hit");
520 | | }
521 | * | if (user == USER11) {
522 | * | fl.log("User USER11 hit");
523 | | }
524 | * | if (user == USER12) {
525 | * | fl.log("User USER12 hit");
526 | | }
527 | * | if (user == USER13) {
528 | * | fl.log("User USER13 hit");
529 | | }
530 | | }
531 | |
532 | * | function _logHandlerTypeCoverage(bytes32 handlerType) internal {
533 | * | if (handlerType == bytes32(0)) {
534 | | fl.log("HandlerType is empty");
535 | | } else {
536 | * | fl.log("HandlerType is non-empty");
537 | | }
538 | | }
539 | |
540 | * | function _logAmountSentCoverage(uint256 amountSent) internal {
541 | * | if (amountSent == 0) {
542 | * | fl.log("AmountSent is 0");
543 | | }
544 | * | if (amountSent > 0 && amountSent <= 1e6) {
545 | * | fl.log("AmountSent is between 0 and 1e6");
546 | | }
547 | * | if (amountSent > 1e6 && amountSent <= 1e12) {
548 | * | fl.log("AmountSent is between 1e6 and 1e12");
549 | | }
550 | * | if (amountSent > 1e12 && amountSent <= 1e18) {
551 | * | fl.log("AmountSent is between 1e12 and 1e18");
552 | | }
553 | * | if (amountSent > 1e18 && amountSent <= 1e24) {
554 | * | fl.log("AmountSent is between 1e18 and 1e24");
555 | | }
556 | * | if (amountSent > 1e24) {
557 | | fl.log("AmountSent is greater than 1e24");
558 | | }
559 | | }
560 | |
561 | * | function _logIsCloseCoverage(bool isClose) internal {
562 | * | if (isClose) {
563 | * | fl.log("IsClose is true");
564 | | } else {
565 | * | fl.log("IsClose is false");
566 | | }
567 | | }
568 | | }
569 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/DecreasePositionInfoCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract DecreasePositionInfoCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ DECREASE POSITION
10 | | // __^ __( \.__) ) GET POSITION INFO
11 | | // (@)<_____>__(_____)____/ COVERAGE
12 | |
13 | | function _checkDecreaseOrderAndGetPositionCoverage(
14 | | Position.Props memory position
15 | | ) internal {
16 | | _logPositionAccountCoverage_decreasePosition(
17 | | position.addresses.account
18 | | );
19 | | _logPositionMarketCoverage_decreasePosition(position.addresses.market);
20 | | _logPositionCollateralTokenCoverage_decreasePosition(
21 | | position.addresses.collateralToken
22 | | );
23 | | _logPositionSizeInUsdCoverage_decreasePosition(
24 | | position.numbers.sizeInUsd
25 | | );
26 | | _logPositionSizeInTokensCoverage_decreasePosition(
27 | | position.numbers.sizeInTokens
28 | | );
29 | | _logPositionCollateralAmountCoverage_decreasePosition(
30 | | position.numbers.collateralAmount
31 | | );
32 | | _logPositionBorrowingFactorCoverage_decreasePosition(
33 | | position.numbers.borrowingFactor
34 | | );
35 | | _logPositionFundingFeeAmountPerSizeCoverage_decreasePosition(
36 | | position.numbers.fundingFeeAmountPerSize
37 | | );
38 | | _logPositionLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
39 | | position.numbers.longTokenClaimableFundingAmountPerSize
40 | | );
41 | | _logPositionShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
42 | | position.numbers.shortTokenClaimableFundingAmountPerSize
43 | | );
44 | | _logPositionIncreasedAtBlockCoverage_decreasePosition(
45 | | position.numbers.increasedAtBlock
46 | | );
47 | | _logPositionDecreasedAtBlockCoverage_decreasePosition(
48 | | position.numbers.decreasedAtBlock
49 | | );
50 | | _logPositionIncreasedAtTimeCoverage_decreasePosition(
51 | | position.numbers.increasedAtTime
52 | | );
53 | | _logPositionDecreasedAtTimeCoverage_decreasePosition(
54 | | position.numbers.decreasedAtTime
55 | | );
56 | | _logPositionIsLongCoverage_decreasePosition(position.flags.isLong);
57 | | }
58 | |
59 | | function _logPositionAccountCoverage_decreasePosition(
60 | | address account
61 | | ) internal {
62 | | if (account == USER0) {
63 | | fl.log("PositionFees account USER0 hit");
64 | | }
65 | | if (account == USER1) {
66 | | fl.log("PositionFees account USER1 hit");
67 | | }
68 | | if (account == USER2) {
69 | | fl.log("PositionFees account USER2 hit");
70 | | }
71 | | if (account == USER3) {
72 | | fl.log("PositionFees account USER3 hit");
73 | | }
74 | | if (account == USER4) {
75 | | fl.log("PositionFees account USER4 hit");
76 | | }
77 | | if (account == USER5) {
78 | | fl.log("PositionFees account USER5 hit");
79 | | }
80 | | if (account == USER6) {
81 | | fl.log("PositionFees account USER6 hit");
82 | | }
83 | | if (account == USER7) {
84 | | fl.log("PositionFees account USER7 hit");
85 | | }
86 | | if (account == USER8) {
87 | | fl.log("PositionFees account USER8 hit");
88 | | }
89 | | if (account == USER9) {
90 | | fl.log("PositionFees account USER9 hit");
91 | | }
92 | | if (account == USER10) {
93 | | fl.log("PositionFees account USER10 hit");
94 | | }
95 | | if (account == USER11) {
96 | | fl.log("PositionFees account USER11 hit");
97 | | }
98 | | if (account == USER12) {
99 | | fl.log("PositionFees account USER12 hit");
100 | | }
101 | | if (account == USER13) {
102 | | fl.log("PositionFees account USER13 hit");
103 | | }
104 | | }
105 | | function _logPositionMarketCoverage_decreasePosition(
106 | | address market
107 | | ) internal {
108 | | if (market == address(market_0_WETH_USDC)) {
109 | | fl.log("Position market market_0_WETH_USDC hit");
110 | | }
111 | |
112 | | if (market == address(market_WBTC_WBTC_USDC)) {
113 | | fl.log("Position market market_WBTC_WBTC_USDC hit");
114 | | }
115 | | if (market == address(market_WETH_WETH_USDC)) {
116 | | fl.log("Position market market_WETH_WETH_USDC hit");
117 | | }
118 | | if (market == address(market_WETH_WETH_USDT)) {
119 | | fl.log("Position market market_WETH_WETH_USDT hit");
120 | | }
121 | | }
122 | |
123 | | function _logPositionCollateralTokenCoverage_decreasePosition(
124 | | address collateralToken
125 | | ) internal {
126 | | if (collateralToken == address(WETH)) {
127 | | fl.log("Position collateralToken is WETH");
128 | | }
129 | | if (collateralToken == address(WBTC)) {
130 | | fl.log("Position collateralToken is WBTC");
131 | | }
132 | | if (collateralToken == address(USDC)) {
133 | | fl.log("Position collateralToken is USDC");
134 | | }
135 | | if (collateralToken == address(USDT)) {
136 | | fl.log("Position collateralToken is USDT");
137 | | }
138 | | if (collateralToken == address(SOL)) {
139 | | fl.log("Position collateralToken is SOL");
140 | | }
141 | | }
142 | |
143 | | function _logPositionSizeInUsdCoverage_decreasePosition(
144 | | uint256 sizeInUsd
145 | | ) internal {
146 | | if (sizeInUsd == 0) {
147 | | fl.log("Position sizeInUsd is 0");
148 | | }
149 | | if (sizeInUsd > 0 && sizeInUsd <= 1e6) {
150 | | fl.log("Position sizeInUsd is between 0 and 1e6");
151 | | }
152 | | if (sizeInUsd > 1e6 && sizeInUsd <= 1e12) {
153 | | fl.log("Position sizeInUsd is between 1e6 and 1e12");
154 | | }
155 | | if (sizeInUsd > 1e12 && sizeInUsd <= 1e18) {
156 | | fl.log("Position sizeInUsd is between 1e12 and 1e18");
157 | | }
158 | | if (sizeInUsd > 1e18 && sizeInUsd <= 1e24) {
159 | | fl.log("Position sizeInUsd is between 1e18 and 1e24");
160 | | }
161 | | if (sizeInUsd > 1e24) {
162 | | fl.log("Position sizeInUsd is greater than 1e24");
163 | | }
164 | | }
165 | |
166 | | function _logPositionSizeInTokensCoverage_decreasePosition(
167 | | uint256 sizeInTokens
168 | | ) internal {
169 | | if (sizeInTokens == 0) {
170 | | fl.log("Position sizeInTokens is 0");
171 | | }
172 | | if (sizeInTokens > 0 && sizeInTokens <= 1e6) {
173 | | fl.log("Position sizeInTokens is between 0 and 1e6");
174 | | }
175 | | if (sizeInTokens > 1e6 && sizeInTokens <= 1e12) {
176 | | fl.log("Position sizeInTokens is between 1e6 and 1e12");
177 | | }
178 | | if (sizeInTokens > 1e12 && sizeInTokens <= 1e18) {
179 | | fl.log("Position sizeInTokens is between 1e12 and 1e18");
180 | | }
181 | | if (sizeInTokens > 1e18 && sizeInTokens <= 1e24) {
182 | | fl.log("Position sizeInTokens is between 1e18 and 1e24");
183 | | }
184 | | if (sizeInTokens > 1e24) {
185 | | fl.log("Position sizeInTokens is greater than 1e24");
186 | | }
187 | | }
188 | |
189 | | function _logPositionCollateralAmountCoverage_decreasePosition(
190 | | uint256 collateralAmount
191 | | ) internal {
192 | | if (collateralAmount == 0) {
193 | | fl.log("Position collateralAmount is 0");
194 | | }
195 | | if (collateralAmount > 0 && collateralAmount <= 1e6) {
196 | | fl.log("Position collateralAmount is between 0 and 1e6");
197 | | }
198 | | if (collateralAmount > 1e6 && collateralAmount <= 1e12) {
199 | | fl.log("Position collateralAmount is between 1e6 and 1e12");
200 | | }
201 | | if (collateralAmount > 1e12 && collateralAmount <= 1e18) {
202 | | fl.log("Position collateralAmount is between 1e12 and 1e18");
203 | | }
204 | | if (collateralAmount > 1e18 && collateralAmount <= 1e24) {
205 | | fl.log("Position collateralAmount is between 1e18 and 1e24");
206 | | }
207 | | if (collateralAmount > 1e24) {
208 | | fl.log("Position collateralAmount is greater than 1e24");
209 | | }
210 | | }
211 | |
212 | | function _logPositionBorrowingFactorCoverage_decreasePosition(
213 | | uint256 borrowingFactor
214 | | ) internal {
215 | | if (borrowingFactor == 0) {
216 | | fl.log("Position borrowingFactor is 0");
217 | | }
218 | | if (borrowingFactor > 0 && borrowingFactor <= 1e6) {
219 | | fl.log("Position borrowingFactor is between 0 and 1e6");
220 | | }
221 | | if (borrowingFactor > 1e6 && borrowingFactor <= 1e12) {
222 | | fl.log("Position borrowingFactor is between 1e6 and 1e12");
223 | | }
224 | | if (borrowingFactor > 1e12 && borrowingFactor <= 1e18) {
225 | | fl.log("Position borrowingFactor is between 1e12 and 1e18");
226 | | }
227 | | if (borrowingFactor > 1e18 && borrowingFactor <= 1e24) {
228 | | fl.log("Position borrowingFactor is between 1e18 and 1e24");
229 | | }
230 | | if (borrowingFactor > 1e24) {
231 | | fl.log("Position borrowingFactor is greater than 1e24");
232 | | }
233 | | }
234 | |
235 | | function _logPositionFundingFeeAmountPerSizeCoverage_decreasePosition(
236 | | uint256 fundingFeeAmountPerSize
237 | | ) internal {
238 | | if (fundingFeeAmountPerSize == 0) {
239 | | fl.log("Position fundingFeeAmountPerSize is 0");
240 | | }
241 | | if (fundingFeeAmountPerSize > 0 && fundingFeeAmountPerSize <= 1e6) {
242 | | fl.log("Position fundingFeeAmountPerSize is between 0 and 1e6");
243 | | }
244 | | if (fundingFeeAmountPerSize > 1e6 && fundingFeeAmountPerSize <= 1e12) {
245 | | fl.log("Position fundingFeeAmountPerSize is between 1e6 and 1e12");
246 | | }
247 | | if (fundingFeeAmountPerSize > 1e12 && fundingFeeAmountPerSize <= 1e18) {
248 | | fl.log("Position fundingFeeAmountPerSize is between 1e12 and 1e18");
249 | | }
250 | | if (fundingFeeAmountPerSize > 1e18 && fundingFeeAmountPerSize <= 1e24) {
251 | | fl.log("Position fundingFeeAmountPerSize is between 1e18 and 1e24");
252 | | }
253 | | if (fundingFeeAmountPerSize > 1e24) {
254 | | fl.log("Position fundingFeeAmountPerSize is greater than 1e24");
255 | | }
256 | | }
257 | |
258 | | function _logPositionLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
259 | | uint256 longTokenClaimableFundingAmountPerSize
260 | | ) internal {
261 | | if (longTokenClaimableFundingAmountPerSize == 0) {
262 | | fl.log("Position longTokenClaimableFundingAmountPerSize is 0");
263 | | }
264 | | if (
265 | | longTokenClaimableFundingAmountPerSize > 0 &&
266 | | longTokenClaimableFundingAmountPerSize <= 1e6
267 | | ) {
268 | | fl.log(
269 | | "Position longTokenClaimableFundingAmountPerSize is between 0 and 1e6"
270 | | );
271 | | }
272 | | if (
273 | | longTokenClaimableFundingAmountPerSize > 1e6 &&
274 | | longTokenClaimableFundingAmountPerSize <= 1e12
275 | | ) {
276 | | fl.log(
277 | | "Position longTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
278 | | );
279 | | }
280 | | if (
281 | | longTokenClaimableFundingAmountPerSize > 1e12 &&
282 | | longTokenClaimableFundingAmountPerSize <= 1e18
283 | | ) {
284 | | fl.log(
285 | | "Position longTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
286 | | );
287 | | }
288 | | if (
289 | | longTokenClaimableFundingAmountPerSize > 1e18 &&
290 | | longTokenClaimableFundingAmountPerSize <= 1e24
291 | | ) {
292 | | fl.log(
293 | | "Position longTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
294 | | );
295 | | }
296 | | if (longTokenClaimableFundingAmountPerSize > 1e24) {
297 | | fl.log(
298 | | "Position longTokenClaimableFundingAmountPerSize is greater than 1e24"
299 | | );
300 | | }
301 | | }
302 | |
303 | | function _logPositionShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
304 | | uint256 shortTokenClaimableFundingAmountPerSize
305 | | ) internal {
306 | | if (shortTokenClaimableFundingAmountPerSize == 0) {
307 | | fl.log("Position shortTokenClaimableFundingAmountPerSize is 0");
308 | | }
309 | | if (
310 | | shortTokenClaimableFundingAmountPerSize > 0 &&
311 | | shortTokenClaimableFundingAmountPerSize <= 1e6
312 | | ) {
313 | | fl.log(
314 | | "Position shortTokenClaimableFundingAmountPerSize is between 0 and 1e6"
315 | | );
316 | | }
317 | | if (
318 | | shortTokenClaimableFundingAmountPerSize > 1e6 &&
319 | | shortTokenClaimableFundingAmountPerSize <= 1e12
320 | | ) {
321 | | fl.log(
322 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
323 | | );
324 | | }
325 | | if (
326 | | shortTokenClaimableFundingAmountPerSize > 1e12 &&
327 | | shortTokenClaimableFundingAmountPerSize <= 1e18
328 | | ) {
329 | | fl.log(
330 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
331 | | );
332 | | }
333 | | if (
334 | | shortTokenClaimableFundingAmountPerSize > 1e18 &&
335 | | shortTokenClaimableFundingAmountPerSize <= 1e24
336 | | ) {
337 | | fl.log(
338 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
339 | | );
340 | | }
341 | | if (shortTokenClaimableFundingAmountPerSize > 1e24) {
342 | | fl.log(
343 | | "Position shortTokenClaimableFundingAmountPerSize is greater than 1e24"
344 | | );
345 | | }
346 | | }
347 | |
348 | | function _logPositionIncreasedAtBlockCoverage_decreasePosition(
349 | | uint256 increasedAtBlock
350 | | ) internal {
351 | | if (increasedAtBlock == 0) {
352 | | fl.log("Position increasedAtBlock is 0");
353 | | } else {
354 | | fl.log("Position increasedAtBlock is non-zero");
355 | | }
356 | | }
357 | |
358 | | function _logPositionDecreasedAtBlockCoverage_decreasePosition(
359 | | uint256 decreasedAtBlock
360 | | ) internal {
361 | | if (decreasedAtBlock == 0) {
362 | | fl.log("Position decreasedAtBlock is 0");
363 | | } else {
364 | | fl.log("Position decreasedAtBlock is non-zero");
365 | | }
366 | | }
367 | |
368 | | function _logPositionIncreasedAtTimeCoverage_decreasePosition(
369 | | uint256 increasedAtTime
370 | | ) internal {
371 | | if (increasedAtTime == 0) {
372 | | fl.log("Position increasedAtTime is 0");
373 | | } else {
374 | | fl.log("Position increasedAtTime is non-zero");
375 | | }
376 | | }
377 | |
378 | | function _logPositionDecreasedAtTimeCoverage_decreasePosition(
379 | | uint256 decreasedAtTime
380 | | ) internal {
381 | | if (decreasedAtTime == 0) {
382 | | fl.log("Position decreasedAtTime is 0");
383 | | } else {
384 | | fl.log("Position decreasedAtTime is non-zero");
385 | | }
386 | | }
387 | |
388 | | function _logPositionIsLongCoverage_decreasePosition(bool isLong) internal {
389 | | if (isLong) {
390 | | fl.log("Position isLong is true");
391 | | } else {
392 | | fl.log("Position isLong is false");
393 | | }
394 | | }
395 | |
396 | | function _checkDecreaseOrderAndGetPositionInfoCoverage(
397 | | ReaderUtils.PositionInfo memory positionInfo
398 | | ) internal {
399 | | // PositionFees
400 | | _logPositionFeesReferralCodeCoverage_decreasePosition(
401 | | positionInfo.fees.referral.referralCode
402 | | );
403 | | _logPositionFeesAffiliateCoverage_decreasePosition(
404 | | positionInfo.fees.referral.affiliate
405 | | );
406 | | _logPositionFeesTraderCoverage_decreasePosition(
407 | | positionInfo.fees.referral.trader
408 | | );
409 | | _logPositionFeesTotalRebateFactorCoverage_decreasePosition(
410 | | positionInfo.fees.referral.totalRebateFactor
411 | | );
412 | | _logPositionFeesTraderDiscountFactorCoverage_decreasePosition(
413 | | positionInfo.fees.referral.traderDiscountFactor
414 | | );
415 | | _logPositionFeesTotalRebateAmountCoverage_decreasePosition(
416 | | positionInfo.fees.referral.totalRebateAmount
417 | | );
418 | | _logPositionFeesTraderDiscountAmountCoverage_decreasePosition(
419 | | positionInfo.fees.referral.traderDiscountAmount
420 | | );
421 | | _logPositionFeesAffiliateRewardAmountCoverage_decreasePosition(
422 | | positionInfo.fees.referral.affiliateRewardAmount
423 | | );
424 | | _logPositionFeesFundingFeeAmountCoverage_decreasePosition(
425 | | positionInfo.fees.funding.fundingFeeAmount
426 | | );
427 | | _logPositionFeesClaimableLongTokenAmountCoverage_decreasePosition(
428 | | positionInfo.fees.funding.claimableLongTokenAmount
429 | | );
430 | | _logPositionFeesClaimableShortTokenAmountCoverage_decreasePosition(
431 | | positionInfo.fees.funding.claimableShortTokenAmount
432 | | );
433 | | _logPositionFeesLatestFundingFeeAmountPerSizeCoverage_decreasePosition(
434 | | positionInfo.fees.funding.latestFundingFeeAmountPerSize
435 | | );
436 | | _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
437 | | positionInfo
438 | | .fees
439 | | .funding
440 | | .latestLongTokenClaimableFundingAmountPerSize
441 | | );
442 | | _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
443 | | positionInfo
444 | | .fees
445 | | .funding
446 | | .latestShortTokenClaimableFundingAmountPerSize
447 | | );
448 | | _logPositionFeesBorrowingFeeUsdCoverage_decreasePosition(
449 | | positionInfo.fees.borrowing.borrowingFeeUsd
450 | | );
451 | | _logPositionFeesBorrowingFeeAmountCoverage_decreasePosition(
452 | | positionInfo.fees.borrowing.borrowingFeeAmount
453 | | );
454 | | _logPositionFeesBorrowingFeeReceiverFactorCoverage_decreasePosition(
455 | | positionInfo.fees.borrowing.borrowingFeeReceiverFactor
456 | | );
457 | | _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage_decreasePosition(
458 | | positionInfo.fees.borrowing.borrowingFeeAmountForFeeReceiver
459 | | );
460 | | _logPositionFeesUiFeeReceiverCoverage_decreasePosition(
461 | | positionInfo.fees.ui.uiFeeReceiver
462 | | );
463 | | _logPositionFeesUiFeeReceiverFactorCoverage_decreasePosition(
464 | | positionInfo.fees.ui.uiFeeReceiverFactor
465 | | );
466 | | _logPositionFeesUiFeeAmountCoverage_decreasePosition(
467 | | positionInfo.fees.ui.uiFeeAmount
468 | | );
469 | | _logPositionFeesCollateralTokenPriceCoverage_decreasePosition(
470 | | positionInfo.fees.collateralTokenPrice.max
471 | | );
472 | |
473 | | _logPositionFeesPositionFeeFactorCoverage_decreasePosition(
474 | | positionInfo.fees.positionFeeFactor
475 | | );
476 | | _logPositionFeesProtocolFeeAmountCoverage_decreasePosition(
477 | | positionInfo.fees.protocolFeeAmount
478 | | );
479 | | _logPositionFeesPositionFeeReceiverFactorCoverage_decreasePosition(
480 | | positionInfo.fees.positionFeeReceiverFactor
481 | | );
482 | | _logPositionFeesFeeReceiverAmountCoverage_decreasePosition(
483 | | positionInfo.fees.feeReceiverAmount
484 | | );
485 | | _logPositionFeesFeeAmountForPoolCoverage_decreasePosition(
486 | | positionInfo.fees.feeAmountForPool
487 | | );
488 | | _logPositionFeesPositionFeeAmountForPoolCoverage_decreasePosition(
489 | | positionInfo.fees.positionFeeAmountForPool
490 | | );
491 | | _logPositionFeesPositionFeeAmountCoverage_decreasePosition(
492 | | positionInfo.fees.positionFeeAmount
493 | | );
494 | | _logPositionFeesTotalCostAmountExcludingFundingCoverage_decreasePosition(
495 | | positionInfo.fees.totalCostAmountExcludingFunding
496 | | );
497 | | _logPositionFeesTotalCostAmountCoverage_decreasePosition(
498 | | positionInfo.fees.totalCostAmount
499 | | );
500 | |
501 | | // ExecutionPriceResult
502 | | _logExecutionPriceResultPriceImpactUsdCoverage_decreasePosition(
503 | | positionInfo.executionPriceResult.priceImpactUsd
504 | | );
505 | | _logExecutionPriceResultPriceImpactDiffUsdCoverage_decreasePosition(
506 | | positionInfo.executionPriceResult.priceImpactDiffUsd
507 | | );
508 | | _logExecutionPriceResultExecutionPriceCoverage_decreasePosition(
509 | | positionInfo.executionPriceResult.executionPrice
510 | | );
511 | |
512 | | _logPositionInfoBasePnlUsdCoverage_decreasePosition(
513 | | positionInfo.basePnlUsd
514 | | );
515 | | _logPositionInfoUncappedBasePnlUsdCoverage_decreasePosition(
516 | | positionInfo.uncappedBasePnlUsd
517 | | );
518 | | _logPositionInfoPnlAfterPriceImpactUsdCoverage_decreasePosition(
519 | | positionInfo.pnlAfterPriceImpactUsd
520 | | );
521 | | }
522 | |
523 | | function _logPositionFeesReferralCodeCoverage_decreasePosition(
524 | | bytes32 referralCode
525 | | ) internal {
526 | | if (referralCode == bytes32(0)) {
527 | | fl.log("PositionFees referralCode is empty");
528 | | } else {
529 | | fl.log("PositionFees referralCode is non-empty");
530 | | }
531 | | }
532 | |
533 | | function _logPositionFeesAffiliateCoverage_decreasePosition(
534 | | address affiliate
535 | | ) internal {
536 | | if (affiliate == address(0)) {
537 | | fl.log("PositionFees affiliate is address(0)");
538 | | } else {
539 | | fl.log("PositionFees affiliate is non-zero address");
540 | | }
541 | | }
542 | |
543 | | function _logPositionFeesTraderCoverage_decreasePosition(
544 | | address trader
545 | | ) internal {
546 | | if (trader == USER0) {
547 | | fl.log("PositionFees trader USER0 hit");
548 | | }
549 | | if (trader == USER1) {
550 | | fl.log("PositionFees trader USER1 hit");
551 | | }
552 | | if (trader == USER2) {
553 | | fl.log("PositionFees trader USER2 hit");
554 | | }
555 | | if (trader == USER3) {
556 | | fl.log("PositionFees trader USER3 hit");
557 | | }
558 | | if (trader == USER4) {
559 | | fl.log("PositionFees trader USER4 hit");
560 | | }
561 | | if (trader == USER5) {
562 | | fl.log("PositionFees trader USER5 hit");
563 | | }
564 | | if (trader == USER6) {
565 | | fl.log("PositionFees trader USER6 hit");
566 | | }
567 | | if (trader == USER7) {
568 | | fl.log("PositionFees trader USER7 hit");
569 | | }
570 | | if (trader == USER8) {
571 | | fl.log("PositionFees trader USER8 hit");
572 | | }
573 | | if (trader == USER9) {
574 | | fl.log("PositionFees trader USER9 hit");
575 | | }
576 | | if (trader == USER10) {
577 | | fl.log("PositionFees trader USER10 hit");
578 | | }
579 | | if (trader == USER11) {
580 | | fl.log("PositionFees trader USER11 hit");
581 | | }
582 | | if (trader == USER12) {
583 | | fl.log("PositionFees trader USER12 hit");
584 | | }
585 | | if (trader == USER13) {
586 | | fl.log("PositionFees trader USER13 hit");
587 | | }
588 | | }
589 | |
590 | | function _logPositionFeesTotalRebateFactorCoverage_decreasePosition(
591 | | uint256 totalRebateFactor
592 | | ) internal {
593 | | if (totalRebateFactor == 0) {
594 | | fl.log("PositionFees totalRebateFactor is 0");
595 | | }
596 | | if (totalRebateFactor > 0 && totalRebateFactor <= 1e6) {
597 | | fl.log("PositionFees totalRebateFactor is between 0 and 1e6");
598 | | }
599 | | if (totalRebateFactor > 1e6 && totalRebateFactor <= 1e12) {
600 | | fl.log("PositionFees totalRebateFactor is between 1e6 and 1e12");
601 | | }
602 | | if (totalRebateFactor > 1e12 && totalRebateFactor <= 1e18) {
603 | | fl.log("PositionFees totalRebateFactor is between 1e12 and 1e18");
604 | | }
605 | | if (totalRebateFactor > 1e18 && totalRebateFactor <= 1e24) {
606 | | fl.log("PositionFees totalRebateFactor is between 1e18 and 1e24");
607 | | }
608 | | if (totalRebateFactor > 1e24) {
609 | | fl.log("PositionFees totalRebateFactor is greater than 1e24");
610 | | }
611 | | }
612 | |
613 | | function _logPositionFeesTraderDiscountFactorCoverage_decreasePosition(
614 | | uint256 traderDiscountFactor
615 | | ) internal {
616 | | if (traderDiscountFactor == 0) {
617 | | fl.log("PositionFees traderDiscountFactor is 0");
618 | | }
619 | | if (traderDiscountFactor > 0 && traderDiscountFactor <= 1e6) {
620 | | fl.log("PositionFees traderDiscountFactor is between 0 and 1e6");
621 | | }
622 | | if (traderDiscountFactor > 1e6 && traderDiscountFactor <= 1e12) {
623 | | fl.log("PositionFees traderDiscountFactor is between 1e6 and 1e12");
624 | | }
625 | | if (traderDiscountFactor > 1e12 && traderDiscountFactor <= 1e18) {
626 | | fl.log(
627 | | "PositionFees traderDiscountFactor is between 1e12 and 1e18"
628 | | );
629 | | }
630 | | if (traderDiscountFactor > 1e18 && traderDiscountFactor <= 1e24) {
631 | | fl.log(
632 | | "PositionFees traderDiscountFactor is between 1e18 and 1e24"
633 | | );
634 | | }
635 | | if (traderDiscountFactor > 1e24) {
636 | | fl.log("PositionFees traderDiscountFactor is greater than 1e24");
637 | | }
638 | | }
639 | |
640 | | function _logPositionFeesTotalRebateAmountCoverage_decreasePosition(
641 | | uint256 totalRebateAmount
642 | | ) internal {
643 | | if (totalRebateAmount == 0) {
644 | | fl.log("PositionFees totalRebateAmount is 0");
645 | | }
646 | | if (totalRebateAmount > 0 && totalRebateAmount <= 1e6) {
647 | | fl.log("PositionFees totalRebateAmount is between 0 and 1e6");
648 | | }
649 | | if (totalRebateAmount > 1e6 && totalRebateAmount <= 1e12) {
650 | | fl.log("PositionFees totalRebateAmount is between 1e6 and 1e12");
651 | | }
652 | | if (totalRebateAmount > 1e12 && totalRebateAmount <= 1e18) {
653 | | fl.log("PositionFees totalRebateAmount is between 1e12 and 1e18");
654 | | }
655 | | if (totalRebateAmount > 1e18 && totalRebateAmount <= 1e24) {
656 | | fl.log("PositionFees totalRebateAmount is between 1e18 and 1e24");
657 | | }
658 | | if (totalRebateAmount > 1e24) {
659 | | fl.log("PositionFees totalRebateAmount is greater than 1e24");
660 | | }
661 | | }
662 | |
663 | | function _logPositionFeesTraderDiscountAmountCoverage_decreasePosition(
664 | | uint256 traderDiscountAmount
665 | | ) internal {
666 | | if (traderDiscountAmount == 0) {
667 | | fl.log("PositionFees traderDiscountAmount is 0");
668 | | }
669 | | if (traderDiscountAmount > 0 && traderDiscountAmount <= 1e6) {
670 | | fl.log("PositionFees traderDiscountAmount is between 0 and 1e6");
671 | | }
672 | | if (traderDiscountAmount > 1e6 && traderDiscountAmount <= 1e12) {
673 | | fl.log("PositionFees traderDiscountAmount is between 1e6 and 1e12");
674 | | }
675 | | if (traderDiscountAmount > 1e12 && traderDiscountAmount <= 1e18) {
676 | | fl.log(
677 | | "PositionFees traderDiscountAmount is between 1e12 and 1e18"
678 | | );
679 | | }
680 | | if (traderDiscountAmount > 1e18 && traderDiscountAmount <= 1e24) {
681 | | fl.log(
682 | | "PositionFees traderDiscountAmount is between 1e18 and 1e24"
683 | | );
684 | | }
685 | | if (traderDiscountAmount > 1e24) {
686 | | fl.log("PositionFees traderDiscountAmount is greater than 1e24");
687 | | }
688 | | }
689 | |
690 | | function _logPositionFeesAffiliateRewardAmountCoverage_decreasePosition(
691 | | uint256 affiliateRewardAmount
692 | | ) internal {
693 | | if (affiliateRewardAmount == 0) {
694 | | fl.log("PositionFees affiliateRewardAmount is 0");
695 | | }
696 | | if (affiliateRewardAmount > 0 && affiliateRewardAmount <= 1e6) {
697 | | fl.log("PositionFees affiliateRewardAmount is between 0 and 1e6");
698 | | }
699 | | if (affiliateRewardAmount > 1e6 && affiliateRewardAmount <= 1e12) {
700 | | fl.log(
701 | | "PositionFees affiliateRewardAmount is between 1e6 and 1e12"
702 | | );
703 | | }
704 | | if (affiliateRewardAmount > 1e12 && affiliateRewardAmount <= 1e18) {
705 | | fl.log(
706 | | "PositionFees affiliateRewardAmount is between 1e12 and 1e18"
707 | | );
708 | | }
709 | | if (affiliateRewardAmount > 1e18 && affiliateRewardAmount <= 1e24) {
710 | | fl.log(
711 | | "PositionFees affiliateRewardAmount is between 1e18 and 1e24"
712 | | );
713 | | }
714 | | if (affiliateRewardAmount > 1e24) {
715 | | fl.log("PositionFees affiliateRewardAmount is greater than 1e24");
716 | | }
717 | | }
718 | |
719 | | function _logPositionFeesFundingFeeAmountCoverage_decreasePosition(
720 | | uint256 fundingFeeAmount
721 | | ) internal {
722 | | if (fundingFeeAmount == 0) {
723 | | fl.log("PositionFees fundingFeeAmount is 0");
724 | | }
725 | | if (fundingFeeAmount > 0 && fundingFeeAmount <= 1e6) {
726 | | fl.log("PositionFees fundingFeeAmount is between 0 and 1e6");
727 | | }
728 | | if (fundingFeeAmount > 1e6 && fundingFeeAmount <= 1e12) {
729 | | fl.log("PositionFees fundingFeeAmount is between 1e6 and 1e12");
730 | | }
731 | | if (fundingFeeAmount > 1e12 && fundingFeeAmount <= 1e18) {
732 | | fl.log("PositionFees fundingFeeAmount is between 1e12 and 1e18");
733 | | }
734 | | if (fundingFeeAmount > 1e18 && fundingFeeAmount <= 1e24) {
735 | | fl.log("PositionFees fundingFeeAmount is between 1e18 and 1e24");
736 | | }
737 | | if (fundingFeeAmount > 1e24) {
738 | | fl.log("PositionFees fundingFeeAmount is greater than 1e24");
739 | | }
740 | | }
741 | |
742 | | function _logPositionFeesClaimableLongTokenAmountCoverage_decreasePosition(
743 | | uint256 claimableLongTokenAmount
744 | | ) internal {
745 | | if (claimableLongTokenAmount == 0) {
746 | | fl.log("PositionFees claimableLongTokenAmount is 0");
747 | | }
748 | | if (claimableLongTokenAmount > 0 && claimableLongTokenAmount <= 1e6) {
749 | | fl.log(
750 | | "PositionFees claimableLongTokenAmount is between 0 and 1e6"
751 | | );
752 | | }
753 | | if (
754 | | claimableLongTokenAmount > 1e6 && claimableLongTokenAmount <= 1e12
755 | | ) {
756 | | fl.log(
757 | | "PositionFees claimableLongTokenAmount is between 1e6 and 1e12"
758 | | );
759 | | }
760 | | if (
761 | | claimableLongTokenAmount > 1e12 && claimableLongTokenAmount <= 1e18
762 | | ) {
763 | | fl.log(
764 | | "PositionFees claimableLongTokenAmount is between 1e12 and 1e18"
765 | | );
766 | | }
767 | | if (
768 | | claimableLongTokenAmount > 1e18 && claimableLongTokenAmount <= 1e24
769 | | ) {
770 | | fl.log(
771 | | "PositionFees claimableLongTokenAmount is between 1e18 and 1e24"
772 | | );
773 | | }
774 | | if (claimableLongTokenAmount > 1e24) {
775 | | fl.log(
776 | | "PositionFees claimableLongTokenAmount is greater than 1e24"
777 | | );
778 | | }
779 | | }
780 | |
781 | | function _logPositionFeesClaimableShortTokenAmountCoverage_decreasePosition(
782 | | uint256 claimableShortTokenAmount
783 | | ) internal {
784 | | if (claimableShortTokenAmount == 0) {
785 | | fl.log("PositionFees claimableShortTokenAmount is 0");
786 | | }
787 | | if (claimableShortTokenAmount > 0 && claimableShortTokenAmount <= 1e6) {
788 | | fl.log(
789 | | "PositionFees claimableShortTokenAmount is between 0 and 1e6"
790 | | );
791 | | }
792 | | if (
793 | | claimableShortTokenAmount > 1e6 && claimableShortTokenAmount <= 1e12
794 | | ) {
795 | | fl.log(
796 | | "PositionFees claimableShortTokenAmount is between 1e6 and 1e12"
797 | | );
798 | | }
799 | | if (
800 | | claimableShortTokenAmount > 1e12 &&
801 | | claimableShortTokenAmount <= 1e18
802 | | ) {
803 | | fl.log(
804 | | "PositionFees claimableShortTokenAmount is between 1e12 and 1e18"
805 | | );
806 | | }
807 | | if (
808 | | claimableShortTokenAmount > 1e18 &&
809 | | claimableShortTokenAmount <= 1e24
810 | | ) {
811 | | fl.log(
812 | | "PositionFees claimableShortTokenAmount is between 1e18 and 1e24"
813 | | );
814 | | }
815 | | if (claimableShortTokenAmount > 1e24) {
816 | | fl.log(
817 | | "PositionFees claimableShortTokenAmount is greater than 1e24"
818 | | );
819 | | }
820 | | }
821 | |
822 | | function _logPositionFeesLatestFundingFeeAmountPerSizeCoverage_decreasePosition(
823 | | uint256 latestFundingFeeAmountPerSize
824 | | ) internal {
825 | | if (latestFundingFeeAmountPerSize == 0) {
826 | | fl.log("PositionFees latestFundingFeeAmountPerSize is 0");
827 | | }
828 | | if (
829 | | latestFundingFeeAmountPerSize > 0 &&
830 | | latestFundingFeeAmountPerSize <= 1e6
831 | | ) {
832 | | fl.log(
833 | | "PositionFees latestFundingFeeAmountPerSize is between 0 and 1e6"
834 | | );
835 | | }
836 | | if (
837 | | latestFundingFeeAmountPerSize > 1e6 &&
838 | | latestFundingFeeAmountPerSize <= 1e12
839 | | ) {
840 | | fl.log(
841 | | "PositionFees latestFundingFeeAmountPerSize is between 1e6 and 1e12"
842 | | );
843 | | }
844 | | if (
845 | | latestFundingFeeAmountPerSize > 1e12 &&
846 | | latestFundingFeeAmountPerSize <= 1e18
847 | | ) {
848 | | fl.log(
849 | | "PositionFees latestFundingFeeAmountPerSize is between 1e12 and 1e18"
850 | | );
851 | | }
852 | | if (
853 | | latestFundingFeeAmountPerSize > 1e18 &&
854 | | latestFundingFeeAmountPerSize <= 1e24
855 | | ) {
856 | | fl.log(
857 | | "PositionFees latestFundingFeeAmountPerSize is between 1e18 and 1e24"
858 | | );
859 | | }
860 | | if (latestFundingFeeAmountPerSize > 1e24) {
861 | | fl.log(
862 | | "PositionFees latestFundingFeeAmountPerSize is greater than 1e24"
863 | | );
864 | | }
865 | | }
866 | |
867 | | function _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
868 | | uint256 latestLongTokenClaimableFundingAmountPerSize
869 | | ) internal {
870 | | if (latestLongTokenClaimableFundingAmountPerSize == 0) {
871 | | fl.log(
872 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is 0"
873 | | );
874 | | }
875 | | if (
876 | | latestLongTokenClaimableFundingAmountPerSize > 0 &&
877 | | latestLongTokenClaimableFundingAmountPerSize <= 1e6
878 | | ) {
879 | | fl.log(
880 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 0 and 1e6"
881 | | );
882 | | }
883 | | if (
884 | | latestLongTokenClaimableFundingAmountPerSize > 1e6 &&
885 | | latestLongTokenClaimableFundingAmountPerSize <= 1e12
886 | | ) {
887 | | fl.log(
888 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
889 | | );
890 | | }
891 | | if (
892 | | latestLongTokenClaimableFundingAmountPerSize > 1e12 &&
893 | | latestLongTokenClaimableFundingAmountPerSize <= 1e18
894 | | ) {
895 | | fl.log(
896 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
897 | | );
898 | | }
899 | | if (
900 | | latestLongTokenClaimableFundingAmountPerSize > 1e18 &&
901 | | latestLongTokenClaimableFundingAmountPerSize <= 1e24
902 | | ) {
903 | | fl.log(
904 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
905 | | );
906 | | }
907 | | if (latestLongTokenClaimableFundingAmountPerSize > 1e24) {
908 | | fl.log(
909 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is greater than 1e24"
910 | | );
911 | | }
912 | | }
913 | |
914 | | function _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition(
915 | | uint256 latestShortTokenClaimableFundingAmountPerSize
916 | | ) internal {
917 | | if (latestShortTokenClaimableFundingAmountPerSize == 0) {
918 | | fl.log(
919 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is 0"
920 | | );
921 | | }
922 | | if (
923 | | latestShortTokenClaimableFundingAmountPerSize > 0 &&
924 | | latestShortTokenClaimableFundingAmountPerSize <= 1e6
925 | | ) {
926 | | fl.log(
927 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 0 and 1e6"
928 | | );
929 | | }
930 | | if (
931 | | latestShortTokenClaimableFundingAmountPerSize > 1e6 &&
932 | | latestShortTokenClaimableFundingAmountPerSize <= 1e12
933 | | ) {
934 | | fl.log(
935 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
936 | | );
937 | | }
938 | | if (
939 | | latestShortTokenClaimableFundingAmountPerSize > 1e12 &&
940 | | latestShortTokenClaimableFundingAmountPerSize <= 1e18
941 | | ) {
942 | | fl.log(
943 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
944 | | );
945 | | }
946 | | if (
947 | | latestShortTokenClaimableFundingAmountPerSize > 1e18 &&
948 | | latestShortTokenClaimableFundingAmountPerSize <= 1e24
949 | | ) {
950 | | fl.log(
951 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
952 | | );
953 | | }
954 | | if (latestShortTokenClaimableFundingAmountPerSize > 1e24) {
955 | | fl.log(
956 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is greater than 1e24"
957 | | );
958 | | }
959 | | }
960 | |
961 | | function _logPositionFeesBorrowingFeeUsdCoverage_decreasePosition(
962 | | uint256 borrowingFeeUsd
963 | | ) internal {
964 | | if (borrowingFeeUsd == 0) {
965 | | fl.log("PositionFees borrowingFeeUsd is 0");
966 | | }
967 | | if (borrowingFeeUsd > 0 && borrowingFeeUsd <= 1e6) {
968 | | fl.log("PositionFees borrowingFeeUsd is between 0 and 1e6");
969 | | }
970 | | if (borrowingFeeUsd > 1e6 && borrowingFeeUsd <= 1e12) {
971 | | fl.log("PositionFees borrowingFeeUsd is between 1e6 and 1e12");
972 | | }
973 | | if (borrowingFeeUsd > 1e12 && borrowingFeeUsd <= 1e18) {
974 | | fl.log("PositionFees borrowingFeeUsd is between 1e12 and 1e18");
975 | | }
976 | | if (borrowingFeeUsd > 1e18 && borrowingFeeUsd <= 1e24) {
977 | | fl.log("PositionFees borrowingFeeUsd is between 1e18 and 1e24");
978 | | }
979 | | if (borrowingFeeUsd > 1e24) {
980 | | fl.log("PositionFees borrowingFeeUsd is greater than 1e24");
981 | | }
982 | | }
983 | |
984 | | function _logPositionFeesBorrowingFeeAmountCoverage_decreasePosition(
985 | | uint256 borrowingFeeAmount
986 | | ) internal {
987 | | if (borrowingFeeAmount == 0) {
988 | | fl.log("PositionFees borrowingFeeAmount is 0");
989 | | }
990 | | if (borrowingFeeAmount > 0 && borrowingFeeAmount <= 1e6) {
991 | | fl.log("PositionFees borrowingFeeAmount is between 0 and 1e6");
992 | | }
993 | | if (borrowingFeeAmount > 1e6 && borrowingFeeAmount <= 1e12) {
994 | | fl.log("PositionFees borrowingFeeAmount is between 1e6 and 1e12");
995 | | }
996 | | if (borrowingFeeAmount > 1e12 && borrowingFeeAmount <= 1e18) {
997 | | fl.log("PositionFees borrowingFeeAmount is between 1e12 and 1e18");
998 | | }
999 | | if (borrowingFeeAmount > 1e18 && borrowingFeeAmount <= 1e24) {
1000 | | fl.log("PositionFees borrowingFeeAmount is between 1e18 and 1e24");
1001 | | }
1002 | | if (borrowingFeeAmount > 1e24) {
1003 | | fl.log("PositionFees borrowingFeeAmount is greater than 1e24");
1004 | | }
1005 | | }
1006 | |
1007 | | function _logPositionFeesBorrowingFeeReceiverFactorCoverage_decreasePosition(
1008 | | uint256 borrowingFeeReceiverFactor
1009 | | ) internal {
1010 | | if (borrowingFeeReceiverFactor == 0) {
1011 | | fl.log("PositionFees borrowingFeeReceiverFactor is 0");
1012 | | }
1013 | | if (
1014 | | borrowingFeeReceiverFactor > 0 && borrowingFeeReceiverFactor <= 1e6
1015 | | ) {
1016 | | fl.log(
1017 | | "PositionFees borrowingFeeReceiverFactor is between 0 and 1e6"
1018 | | );
1019 | | }
1020 | | if (
1021 | | borrowingFeeReceiverFactor > 1e6 &&
1022 | | borrowingFeeReceiverFactor <= 1e12
1023 | | ) {
1024 | | fl.log(
1025 | | "PositionFees borrowingFeeReceiverFactor is between 1e6 and 1e12"
1026 | | );
1027 | | }
1028 | | if (
1029 | | borrowingFeeReceiverFactor > 1e12 &&
1030 | | borrowingFeeReceiverFactor <= 1e18
1031 | | ) {
1032 | | fl.log(
1033 | | "PositionFees borrowingFeeReceiverFactor is between 1e12 and 1e18"
1034 | | );
1035 | | }
1036 | | if (
1037 | | borrowingFeeReceiverFactor > 1e18 &&
1038 | | borrowingFeeReceiverFactor <= 1e24
1039 | | ) {
1040 | | fl.log(
1041 | | "PositionFees borrowingFeeReceiverFactor is between 1e18 and 1e24"
1042 | | );
1043 | | }
1044 | | if (borrowingFeeReceiverFactor > 1e24) {
1045 | | fl.log(
1046 | | "PositionFees borrowingFeeReceiverFactor is greater than 1e24"
1047 | | );
1048 | | }
1049 | | }
1050 | |
1051 | | function _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage_decreasePosition(
1052 | | uint256 borrowingFeeAmountForFeeReceiver
1053 | | ) internal {
1054 | | if (borrowingFeeAmountForFeeReceiver == 0) {
1055 | | fl.log("PositionFees borrowingFeeAmountForFeeReceiver is 0");
1056 | | }
1057 | | if (
1058 | | borrowingFeeAmountForFeeReceiver > 0 &&
1059 | | borrowingFeeAmountForFeeReceiver <= 1e6
1060 | | ) {
1061 | | fl.log(
1062 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 0 and 1e6"
1063 | | );
1064 | | }
1065 | | if (
1066 | | borrowingFeeAmountForFeeReceiver > 1e6 &&
1067 | | borrowingFeeAmountForFeeReceiver <= 1e12
1068 | | ) {
1069 | | fl.log(
1070 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e6 and 1e12"
1071 | | );
1072 | | }
1073 | | if (
1074 | | borrowingFeeAmountForFeeReceiver > 1e12 &&
1075 | | borrowingFeeAmountForFeeReceiver <= 1e18
1076 | | ) {
1077 | | fl.log(
1078 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e12 and 1e18"
1079 | | );
1080 | | }
1081 | | if (
1082 | | borrowingFeeAmountForFeeReceiver > 1e18 &&
1083 | | borrowingFeeAmountForFeeReceiver <= 1e24
1084 | | ) {
1085 | | fl.log(
1086 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e18 and 1e24"
1087 | | );
1088 | | }
1089 | | if (borrowingFeeAmountForFeeReceiver > 1e24) {
1090 | | fl.log(
1091 | | "PositionFees borrowingFeeAmountForFeeReceiver is greater than 1e24"
1092 | | );
1093 | | }
1094 | | }
1095 | |
1096 | | function _logPositionFeesUiFeeReceiverCoverage_decreasePosition(
1097 | | address uiFeeReceiver
1098 | | ) internal {
1099 | | if (uiFeeReceiver == address(0)) {
1100 | | fl.log("PositionFees uiFeeReceiver is address(0)");
1101 | | } else {
1102 | | fl.log("PositionFees uiFeeReceiver is non-zero address");
1103 | | }
1104 | | }
1105 | |
1106 | | function _logPositionFeesUiFeeReceiverFactorCoverage_decreasePosition(
1107 | | uint256 uiFeeReceiverFactor
1108 | | ) internal {
1109 | | if (uiFeeReceiverFactor == 0) {
1110 | | fl.log("PositionFees uiFeeReceiverFactor is 0");
1111 | | }
1112 | | if (uiFeeReceiverFactor > 0 && uiFeeReceiverFactor <= 1e6) {
1113 | | fl.log("PositionFees uiFeeReceiverFactor is between 0 and 1e6");
1114 | | }
1115 | | if (uiFeeReceiverFactor > 1e6 && uiFeeReceiverFactor <= 1e12) {
1116 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e6 and 1e12");
1117 | | }
1118 | | if (uiFeeReceiverFactor > 1e12 && uiFeeReceiverFactor <= 1e18) {
1119 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e12 and 1e18");
1120 | | }
1121 | | if (uiFeeReceiverFactor > 1e18 && uiFeeReceiverFactor <= 1e24) {
1122 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e18 and 1e24");
1123 | | }
1124 | | if (uiFeeReceiverFactor > 1e24) {
1125 | | fl.log("PositionFees uiFeeReceiverFactor is greater than 1e24");
1126 | | }
1127 | | }
1128 | |
1129 | | function _logPositionFeesUiFeeAmountCoverage_decreasePosition(
1130 | | uint256 uiFeeAmount
1131 | | ) internal {
1132 | | if (uiFeeAmount == 0) {
1133 | | fl.log("PositionFees uiFeeAmount is 0");
1134 | | }
1135 | | if (uiFeeAmount > 0 && uiFeeAmount <= 1e6) {
1136 | | fl.log("PositionFees uiFeeAmount is between 0 and 1e6");
1137 | | }
1138 | | if (uiFeeAmount > 1e6 && uiFeeAmount <= 1e12) {
1139 | | fl.log("PositionFees uiFeeAmount is between 1e6 and 1e12");
1140 | | }
1141 | | if (uiFeeAmount > 1e12 && uiFeeAmount <= 1e18) {
1142 | | fl.log("PositionFees uiFeeAmount is between 1e12 and 1e18");
1143 | | }
1144 | | if (uiFeeAmount > 1e18 && uiFeeAmount <= 1e24) {
1145 | | fl.log("PositionFees uiFeeAmount is between 1e18 and 1e24");
1146 | | }
1147 | | if (uiFeeAmount > 1e24) {
1148 | | fl.log("PositionFees uiFeeAmount is greater than 1e24");
1149 | | }
1150 | | }
1151 | |
1152 | | function _logPositionFeesCollateralTokenPriceCoverage_decreasePosition(
1153 | | uint256 collateralTokenPrice
1154 | | ) internal {
1155 | | if (collateralTokenPrice == 0) {
1156 | | fl.log("PositionFees collateralTokenPrice is 0");
1157 | | }
1158 | | if (collateralTokenPrice > 0 && collateralTokenPrice <= 1e6) {
1159 | | fl.log("PositionFees collateralTokenPrice is between 0 and 1e6");
1160 | | }
1161 | | if (collateralTokenPrice > 1e6 && collateralTokenPrice <= 1e12) {
1162 | | fl.log("PositionFees collateralTokenPrice is between 1e6 and 1e12");
1163 | | }
1164 | | if (collateralTokenPrice > 1e12 && collateralTokenPrice <= 1e18) {
1165 | | fl.log(
1166 | | "PositionFees collateralTokenPrice is between 1e12 and 1e18"
1167 | | );
1168 | | }
1169 | | if (collateralTokenPrice > 1e18 && collateralTokenPrice <= 1e24) {
1170 | | fl.log(
1171 | | "PositionFees collateralTokenPrice is between 1e18 and 1e24"
1172 | | );
1173 | | }
1174 | | if (collateralTokenPrice > 1e24) {
1175 | | fl.log("PositionFees collateralTokenPrice is greater than 1e24");
1176 | | }
1177 | | }
1178 | |
1179 | | function _logPositionFeesPositionFeeFactorCoverage_decreasePosition(
1180 | | uint256 positionFeeFactor
1181 | | ) internal {
1182 | | if (positionFeeFactor == 0) {
1183 | | fl.log("PositionFees positionFeeFactor is 0");
1184 | | }
1185 | | if (positionFeeFactor > 0 && positionFeeFactor <= 1e6) {
1186 | | fl.log("PositionFees positionFeeFactor is between 0 and 1e6");
1187 | | }
1188 | | if (positionFeeFactor > 1e6 && positionFeeFactor <= 1e12) {
1189 | | fl.log("PositionFees positionFeeFactor is between 1e6 and 1e12");
1190 | | }
1191 | | if (positionFeeFactor > 1e12 && positionFeeFactor <= 1e18) {
1192 | | fl.log("PositionFees positionFeeFactor is between 1e12 and 1e18");
1193 | | }
1194 | | if (positionFeeFactor > 1e18 && positionFeeFactor <= 1e24) {
1195 | | fl.log("PositionFees positionFeeFactor is between 1e18 and 1e24");
1196 | | }
1197 | | if (positionFeeFactor > 1e24) {
1198 | | fl.log("PositionFees positionFeeFactor is greater than 1e24");
1199 | | }
1200 | | }
1201 | | function _logPositionFeesProtocolFeeAmountCoverage_decreasePosition(
1202 | | uint256 protocolFeeAmount
1203 | | ) internal {
1204 | | if (protocolFeeAmount == 0) {
1205 | | fl.log("PositionFees protocolFeeAmount is 0");
1206 | | }
1207 | | if (protocolFeeAmount > 0 && protocolFeeAmount <= 1e6) {
1208 | | fl.log("PositionFees protocolFeeAmount is between 0 and 1e6");
1209 | | }
1210 | | if (protocolFeeAmount > 1e6 && protocolFeeAmount <= 1e12) {
1211 | | fl.log("PositionFees protocolFeeAmount is between 1e6 and 1e12");
1212 | | }
1213 | | if (protocolFeeAmount > 1e12 && protocolFeeAmount <= 1e18) {
1214 | | fl.log("PositionFees protocolFeeAmount is between 1e12 and 1e18");
1215 | | }
1216 | | if (protocolFeeAmount > 1e18 && protocolFeeAmount <= 1e24) {
1217 | | fl.log("PositionFees protocolFeeAmount is between 1e18 and 1e24");
1218 | | }
1219 | | if (protocolFeeAmount > 1e24) {
1220 | | fl.log("PositionFees protocolFeeAmount is greater than 1e24");
1221 | | }
1222 | | }
1223 | | function _logPositionFeesPositionFeeReceiverFactorCoverage_decreasePosition(
1224 | | uint256 positionFeeReceiverFactor
1225 | | ) internal {
1226 | | if (positionFeeReceiverFactor == 0) {
1227 | | fl.log("PositionFees positionFeeReceiverFactor is 0");
1228 | | }
1229 | |
1230 | | if (positionFeeReceiverFactor > 0 && positionFeeReceiverFactor <= 1e6) {
1231 | | fl.log(
1232 | | "PositionFees positionFeeReceiverFactor is between 0 and 1e6"
1233 | | );
1234 | | }
1235 | |
1236 | | if (
1237 | | positionFeeReceiverFactor > 1e6 && positionFeeReceiverFactor <= 1e12
1238 | | ) {
1239 | | fl.log(
1240 | | "PositionFees positionFeeReceiverFactor is between 1e6 and 1e12"
1241 | | );
1242 | | }
1243 | |
1244 | | if (
1245 | | positionFeeReceiverFactor > 1e12 &&
1246 | | positionFeeReceiverFactor <= 1e18
1247 | | ) {
1248 | | fl.log(
1249 | | "PositionFees positionFeeReceiverFactor is between 1e12 and 1e18"
1250 | | );
1251 | | }
1252 | |
1253 | | if (
1254 | | positionFeeReceiverFactor > 1e18 &&
1255 | | positionFeeReceiverFactor <= 1e24
1256 | | ) {
1257 | | fl.log(
1258 | | "PositionFees positionFeeReceiverFactor is between 1e18 and 1e24"
1259 | | );
1260 | | }
1261 | |
1262 | | if (positionFeeReceiverFactor > 1e24) {
1263 | | fl.log(
1264 | | "PositionFees positionFeeReceiverFactor is greater than 1e24"
1265 | | );
1266 | | }
1267 | | }
1268 | |
1269 | | function _logPositionFeesFeeReceiverAmountCoverage_decreasePosition(
1270 | | uint256 feeReceiverAmount
1271 | | ) internal {
1272 | | if (feeReceiverAmount == 0) {
1273 | | fl.log("PositionFees feeReceiverAmount is 0");
1274 | | }
1275 | | if (feeReceiverAmount > 0 && feeReceiverAmount <= 1e6) {
1276 | | fl.log("PositionFees feeReceiverAmount is between 0 and 1e6");
1277 | | }
1278 | | if (feeReceiverAmount > 1e6 && feeReceiverAmount <= 1e12) {
1279 | | fl.log("PositionFees feeReceiverAmount is between 1e6 and 1e12");
1280 | | }
1281 | | if (feeReceiverAmount > 1e12 && feeReceiverAmount <= 1e18) {
1282 | | fl.log("PositionFees feeReceiverAmount is between 1e12 and 1e18");
1283 | | }
1284 | | if (feeReceiverAmount > 1e18 && feeReceiverAmount <= 1e24) {
1285 | | fl.log("PositionFees feeReceiverAmount is between 1e18 and 1e24");
1286 | | }
1287 | | if (feeReceiverAmount > 1e24) {
1288 | | fl.log("PositionFees feeReceiverAmount is greater than 1e24");
1289 | | }
1290 | | }
1291 | |
1292 | | function _logPositionFeesFeeAmountForPoolCoverage_decreasePosition(
1293 | | uint256 feeAmountForPool
1294 | | ) internal {
1295 | | if (feeAmountForPool == 0) {
1296 | | fl.log("PositionFees feeAmountForPool is 0");
1297 | | }
1298 | | if (feeAmountForPool > 0 && feeAmountForPool <= 1e6) {
1299 | | fl.log("PositionFees feeAmountForPool is between 0 and 1e6");
1300 | | }
1301 | | if (feeAmountForPool > 1e6 && feeAmountForPool <= 1e12) {
1302 | | fl.log("PositionFees feeAmountForPool is between 1e6 and 1e12");
1303 | | }
1304 | | if (feeAmountForPool > 1e12 && feeAmountForPool <= 1e18) {
1305 | | fl.log("PositionFees feeAmountForPool is between 1e12 and 1e18");
1306 | | }
1307 | | if (feeAmountForPool > 1e18 && feeAmountForPool <= 1e24) {
1308 | | fl.log("PositionFees feeAmountForPool is between 1e18 and 1e24");
1309 | | }
1310 | | if (feeAmountForPool > 1e24) {
1311 | | fl.log("PositionFees feeAmountForPool is greater than 1e24");
1312 | | }
1313 | | }
1314 | |
1315 | | function _logPositionFeesPositionFeeAmountForPoolCoverage_decreasePosition(
1316 | | uint256 positionFeeAmountForPool
1317 | | ) internal {
1318 | | if (positionFeeAmountForPool == 0) {
1319 | | fl.log("PositionFees positionFeeAmountForPool is 0");
1320 | | }
1321 | | if (positionFeeAmountForPool > 0 && positionFeeAmountForPool <= 1e6) {
1322 | | fl.log(
1323 | | "PositionFees positionFeeAmountForPool is between 0 and 1e6"
1324 | | );
1325 | | }
1326 | | if (
1327 | | positionFeeAmountForPool > 1e6 && positionFeeAmountForPool <= 1e12
1328 | | ) {
1329 | | fl.log(
1330 | | "PositionFees positionFeeAmountForPool is between 1e6 and 1e12"
1331 | | );
1332 | | }
1333 | | if (
1334 | | positionFeeAmountForPool > 1e12 && positionFeeAmountForPool <= 1e18
1335 | | ) {
1336 | | fl.log(
1337 | | "PositionFees positionFeeAmountForPool is between 1e12 and 1e18"
1338 | | );
1339 | | }
1340 | | if (
1341 | | positionFeeAmountForPool > 1e18 && positionFeeAmountForPool <= 1e24
1342 | | ) {
1343 | | fl.log(
1344 | | "PositionFees positionFeeAmountForPool is between 1e18 and 1e24"
1345 | | );
1346 | | }
1347 | | if (positionFeeAmountForPool > 1e24) {
1348 | | fl.log(
1349 | | "PositionFees positionFeeAmountForPool is greater than 1e24"
1350 | | );
1351 | | }
1352 | | }
1353 | |
1354 | | function _logPositionFeesPositionFeeAmountCoverage_decreasePosition(
1355 | | uint256 positionFeeAmount
1356 | | ) internal {
1357 | | if (positionFeeAmount == 0) {
1358 | | fl.log("PositionFees positionFeeAmount is 0");
1359 | | }
1360 | | if (positionFeeAmount > 0 && positionFeeAmount <= 1e6) {
1361 | | fl.log("PositionFees positionFeeAmount is between 0 and 1e6");
1362 | | }
1363 | | if (positionFeeAmount > 1e6 && positionFeeAmount <= 1e12) {
1364 | | fl.log("PositionFees positionFeeAmount is between 1e6 and 1e12");
1365 | | }
1366 | | if (positionFeeAmount > 1e12 && positionFeeAmount <= 1e18) {
1367 | | fl.log("PositionFees positionFeeAmount is between 1e12 and 1e18");
1368 | | }
1369 | | if (positionFeeAmount > 1e18 && positionFeeAmount <= 1e24) {
1370 | | fl.log("PositionFees positionFeeAmount is between 1e18 and 1e24");
1371 | | }
1372 | | if (positionFeeAmount > 1e24) {
1373 | | fl.log("PositionFees positionFeeAmount is greater than 1e24");
1374 | | }
1375 | | }
1376 | |
1377 | | function _logPositionFeesTotalCostAmountExcludingFundingCoverage_decreasePosition(
1378 | | uint256 totalCostAmountExcludingFunding
1379 | | ) internal {
1380 | | if (totalCostAmountExcludingFunding == 0) {
1381 | | fl.log("PositionFees totalCostAmountExcludingFunding is 0");
1382 | | }
1383 | | if (
1384 | | totalCostAmountExcludingFunding > 0 &&
1385 | | totalCostAmountExcludingFunding <= 1e6
1386 | | ) {
1387 | | fl.log(
1388 | | "PositionFees totalCostAmountExcludingFunding is between 0 and 1e6"
1389 | | );
1390 | | }
1391 | | if (
1392 | | totalCostAmountExcludingFunding > 1e6 &&
1393 | | totalCostAmountExcludingFunding <= 1e12
1394 | | ) {
1395 | | fl.log(
1396 | | "PositionFees totalCostAmountExcludingFunding is between 1e6 and 1e12"
1397 | | );
1398 | | }
1399 | | if (
1400 | | totalCostAmountExcludingFunding > 1e12 &&
1401 | | totalCostAmountExcludingFunding <= 1e18
1402 | | ) {
1403 | | fl.log(
1404 | | "PositionFees totalCostAmountExcludingFunding is between 1e12 and 1e18"
1405 | | );
1406 | | }
1407 | | if (
1408 | | totalCostAmountExcludingFunding > 1e18 &&
1409 | | totalCostAmountExcludingFunding <= 1e24
1410 | | ) {
1411 | | fl.log(
1412 | | "PositionFees totalCostAmountExcludingFunding is between 1e18 and 1e24"
1413 | | );
1414 | | }
1415 | | if (totalCostAmountExcludingFunding > 1e24) {
1416 | | fl.log(
1417 | | "PositionFees totalCostAmountExcludingFunding is greater than 1e24"
1418 | | );
1419 | | }
1420 | | }
1421 | |
1422 | | function _logPositionFeesTotalCostAmountCoverage_decreasePosition(
1423 | | uint256 totalCostAmount
1424 | | ) internal {
1425 | | if (totalCostAmount == 0) {
1426 | | fl.log("PositionFees totalCostAmount is 0");
1427 | | }
1428 | | if (totalCostAmount > 0 && totalCostAmount <= 1e6) {
1429 | | fl.log("PositionFees totalCostAmount is between 0 and 1e6");
1430 | | }
1431 | | if (totalCostAmount > 1e6 && totalCostAmount <= 1e12) {
1432 | | fl.log("PositionFees totalCostAmount is between 1e6 and 1e12");
1433 | | }
1434 | | if (totalCostAmount > 1e12 && totalCostAmount <= 1e18) {
1435 | | fl.log("PositionFees totalCostAmount is between 1e12 and 1e18");
1436 | | }
1437 | | if (totalCostAmount > 1e18 && totalCostAmount <= 1e24) {
1438 | | fl.log("PositionFees totalCostAmount is between 1e18 and 1e24");
1439 | | }
1440 | | if (totalCostAmount > 1e24) {
1441 | | fl.log("PositionFees totalCostAmount is greater than 1e24");
1442 | | }
1443 | | }
1444 | |
1445 | | function _logExecutionPriceResultPriceImpactUsdCoverage_decreasePosition(
1446 | | int256 priceImpactUsd
1447 | | ) internal {
1448 | | if (priceImpactUsd == 0) {
1449 | | fl.log("ExecutionPriceResult priceImpactUsd is 0");
1450 | | }
1451 | | if (priceImpactUsd > 0 && priceImpactUsd <= 1e6) {
1452 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and 1e6");
1453 | | }
1454 | | if (priceImpactUsd > 1e6 && priceImpactUsd <= 1e12) {
1455 | | fl.log(
1456 | | "ExecutionPriceResult priceImpactUsd is between 1e6 and 1e12"
1457 | | );
1458 | | }
1459 | | if (priceImpactUsd > 1e12 && priceImpactUsd <= 1e18) {
1460 | | fl.log(
1461 | | "ExecutionPriceResult priceImpactUsd is between 1e12 and 1e18"
1462 | | );
1463 | | }
1464 | | if (priceImpactUsd > 1e18 && priceImpactUsd <= 1e24) {
1465 | | fl.log(
1466 | | "ExecutionPriceResult priceImpactUsd is between 1e18 and 1e24"
1467 | | );
1468 | | }
1469 | | if (priceImpactUsd > 1e24) {
1470 | | fl.log("ExecutionPriceResult priceImpactUsd is greater than 1e24");
1471 | | }
1472 | | if (priceImpactUsd < 0 && priceImpactUsd >= -1e6) {
1473 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and -1e6");
1474 | | }
1475 | | if (priceImpactUsd < -1e6 && priceImpactUsd >= -1e12) {
1476 | | fl.log(
1477 | | "ExecutionPriceResult priceImpactUsd is between -1e6 and -1e12"
1478 | | );
1479 | | }
1480 | | if (priceImpactUsd < -1e12 && priceImpactUsd >= -1e18) {
1481 | | fl.log(
1482 | | "ExecutionPriceResult priceImpactUsd is between -1e12 and -1e18"
1483 | | );
1484 | | }
1485 | | if (priceImpactUsd < -1e18 && priceImpactUsd >= -1e24) {
1486 | | fl.log(
1487 | | "ExecutionPriceResult priceImpactUsd is between -1e18 and -1e24"
1488 | | );
1489 | | }
1490 | | if (priceImpactUsd < -1e24) {
1491 | | fl.log("ExecutionPriceResult priceImpactUsd is less than -1e24");
1492 | | }
1493 | | }
1494 | | function _logExecutionPriceResultPriceImpactDiffUsdCoverage_decreasePosition(
1495 | | uint256 priceImpactDiffUsd
1496 | | ) internal {
1497 | | if (priceImpactDiffUsd == 0) {
1498 | | fl.log("ExecutionPriceResult priceImpactDiffUsd is 0");
1499 | | }
1500 | | if (priceImpactDiffUsd > 0 && priceImpactDiffUsd <= 1e6) {
1501 | | fl.log(
1502 | | "ExecutionPriceResult priceImpactDiffUsd is between 0 and 1e6"
1503 | | );
1504 | | }
1505 | | if (priceImpactDiffUsd > 1e6 && priceImpactDiffUsd <= 1e12) {
1506 | | fl.log(
1507 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e6 and 1e12"
1508 | | );
1509 | | }
1510 | | if (priceImpactDiffUsd > 1e12 && priceImpactDiffUsd <= 1e18) {
1511 | | fl.log(
1512 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e12 and 1e18"
1513 | | );
1514 | | }
1515 | | if (priceImpactDiffUsd > 1e18 && priceImpactDiffUsd <= 1e24) {
1516 | | fl.log(
1517 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e18 and 1e24"
1518 | | );
1519 | | }
1520 | | if (priceImpactDiffUsd > 1e24) {
1521 | | fl.log(
1522 | | "ExecutionPriceResult priceImpactDiffUsd is greater than 1e24"
1523 | | );
1524 | | }
1525 | | }
1526 | | function _logExecutionPriceResultExecutionPriceCoverage_decreasePosition(
1527 | | uint256 executionPrice
1528 | | ) internal {
1529 | | if (executionPrice == 0) {
1530 | | fl.log("ExecutionPriceResult executionPrice is 0");
1531 | | }
1532 | | if (executionPrice > 0 && executionPrice <= 1e6) {
1533 | | fl.log("ExecutionPriceResult executionPrice is between 0 and 1e6");
1534 | | }
1535 | | if (executionPrice > 1e6 && executionPrice <= 1e12) {
1536 | | fl.log(
1537 | | "ExecutionPriceResult executionPrice is between 1e6 and 1e12"
1538 | | );
1539 | | }
1540 | | if (executionPrice > 1e12 && executionPrice <= 1e18) {
1541 | | fl.log(
1542 | | "ExecutionPriceResult executionPrice is between 1e12 and 1e18"
1543 | | );
1544 | | }
1545 | | if (executionPrice > 1e18 && executionPrice <= 1e24) {
1546 | | fl.log(
1547 | | "ExecutionPriceResult executionPrice is between 1e18 and 1e24"
1548 | | );
1549 | | }
1550 | | if (executionPrice > 1e24) {
1551 | | fl.log("ExecutionPriceResult executionPrice is greater than 1e24");
1552 | | }
1553 | | }
1554 | | function _logPositionInfoBasePnlUsdCoverage_decreasePosition(
1555 | | int256 basePnlUsd
1556 | | ) internal {
1557 | | if (basePnlUsd == 0) {
1558 | | fl.log("PositionInfo basePnlUsd is 0");
1559 | | }
1560 | | if (basePnlUsd > 0 && basePnlUsd <= 1e6) {
1561 | | fl.log("PositionInfo basePnlUsd is between 0 and 1e6");
1562 | | }
1563 | | if (basePnlUsd > 1e6 && basePnlUsd <= 1e12) {
1564 | | fl.log("PositionInfo basePnlUsd is between 1e6 and 1e12");
1565 | | }
1566 | | if (basePnlUsd > 1e12 && basePnlUsd <= 1e18) {
1567 | | fl.log("PositionInfo basePnlUsd is between 1e12 and 1e18");
1568 | | }
1569 | | if (basePnlUsd > 1e18 && basePnlUsd <= 1e24) {
1570 | | fl.log("PositionInfo basePnlUsd is between 1e18 and 1e24");
1571 | | }
1572 | | if (basePnlUsd > 1e24) {
1573 | | fl.log("PositionInfo basePnlUsd is greater than 1e24");
1574 | | }
1575 | | if (basePnlUsd < 0 && basePnlUsd >= -1e6) {
1576 | | fl.log("PositionInfo basePnlUsd is between 0 and -1e6");
1577 | | }
1578 | | if (basePnlUsd < -1e6 && basePnlUsd >= -1e12) {
1579 | | fl.log("PositionInfo basePnlUsd is between -1e6 and -1e12");
1580 | | }
1581 | | if (basePnlUsd < -1e12 && basePnlUsd >= -1e18) {
1582 | | fl.log("PositionInfo basePnlUsd is between -1e12 and -1e18");
1583 | | }
1584 | | if (basePnlUsd < -1e18 && basePnlUsd >= -1e24) {
1585 | | fl.log("PositionInfo basePnlUsd is between -1e18 and -1e24");
1586 | | }
1587 | | if (basePnlUsd < -1e24) {
1588 | | fl.log("PositionInfo basePnlUsd is less than -1e24");
1589 | | }
1590 | | }
1591 | | function _logPositionInfoUncappedBasePnlUsdCoverage_decreasePosition(
1592 | | int256 uncappedBasePnlUsd
1593 | | ) internal {
1594 | | if (uncappedBasePnlUsd == 0) {
1595 | | fl.log("PositionInfo uncappedBasePnlUsd is 0");
1596 | | }
1597 | | if (uncappedBasePnlUsd > 0 && uncappedBasePnlUsd <= 1e6) {
1598 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and 1e6");
1599 | | }
1600 | | if (uncappedBasePnlUsd > 1e6 && uncappedBasePnlUsd <= 1e12) {
1601 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e6 and 1e12");
1602 | | }
1603 | | if (uncappedBasePnlUsd > 1e12 && uncappedBasePnlUsd <= 1e18) {
1604 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e12 and 1e18");
1605 | | }
1606 | | if (uncappedBasePnlUsd > 1e18 && uncappedBasePnlUsd <= 1e24) {
1607 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e18 and 1e24");
1608 | | }
1609 | | if (uncappedBasePnlUsd > 1e24) {
1610 | | fl.log("PositionInfo uncappedBasePnlUsd is greater than 1e24");
1611 | | }
1612 | | if (uncappedBasePnlUsd < 0 && uncappedBasePnlUsd >= -1e6) {
1613 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and -1e6");
1614 | | }
1615 | | if (uncappedBasePnlUsd < -1e6 && uncappedBasePnlUsd >= -1e12) {
1616 | | fl.log("PositionInfo uncappedBasePnlUsd is between -1e6 and -1e12");
1617 | | }
1618 | | if (uncappedBasePnlUsd < -1e12 && uncappedBasePnlUsd >= -1e18) {
1619 | | fl.log(
1620 | | "PositionInfo uncappedBasePnlUsd is between -1e12 and -1e18"
1621 | | );
1622 | | }
1623 | | if (uncappedBasePnlUsd < -1e18 && uncappedBasePnlUsd >= -1e24) {
1624 | | fl.log(
1625 | | "PositionInfo uncappedBasePnlUsd is between -1e18 and -1e24"
1626 | | );
1627 | | }
1628 | | if (uncappedBasePnlUsd < -1e24) {
1629 | | fl.log("PositionInfo uncappedBasePnlUsd is less than -1e24");
1630 | | }
1631 | | }
1632 | | function _logPositionInfoPnlAfterPriceImpactUsdCoverage_decreasePosition(
1633 | | int256 pnlAfterPriceImpactUsd
1634 | | ) internal {
1635 | | if (pnlAfterPriceImpactUsd == 0) {
1636 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is 0");
1637 | | }
1638 | | if (pnlAfterPriceImpactUsd > 0 && pnlAfterPriceImpactUsd <= 1e6) {
1639 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and 1e6");
1640 | | }
1641 | | if (pnlAfterPriceImpactUsd > 1e6 && pnlAfterPriceImpactUsd <= 1e12) {
1642 | | fl.log(
1643 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e6 and 1e12"
1644 | | );
1645 | | }
1646 | | if (pnlAfterPriceImpactUsd > 1e12 && pnlAfterPriceImpactUsd <= 1e18) {
1647 | | fl.log(
1648 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e12 and 1e18"
1649 | | );
1650 | | }
1651 | | if (pnlAfterPriceImpactUsd > 1e18 && pnlAfterPriceImpactUsd <= 1e24) {
1652 | | fl.log(
1653 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e18 and 1e24"
1654 | | );
1655 | | }
1656 | | if (pnlAfterPriceImpactUsd > 1e24) {
1657 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is greater than 1e24");
1658 | | }
1659 | | if (pnlAfterPriceImpactUsd < 0 && pnlAfterPriceImpactUsd >= -1e6) {
1660 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and -1e6");
1661 | | }
1662 | | if (pnlAfterPriceImpactUsd < -1e6 && pnlAfterPriceImpactUsd >= -1e12) {
1663 | | fl.log(
1664 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e6 and -1e12"
1665 | | );
1666 | | }
1667 | | if (pnlAfterPriceImpactUsd < -1e12 && pnlAfterPriceImpactUsd >= -1e18) {
1668 | | fl.log(
1669 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e12 and -1e18"
1670 | | );
1671 | | }
1672 | | if (pnlAfterPriceImpactUsd < -1e18 && pnlAfterPriceImpactUsd >= -1e24) {
1673 | | fl.log(
1674 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e18 and -1e24"
1675 | | );
1676 | | }
1677 | | if (pnlAfterPriceImpactUsd < -1e24) {
1678 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is less than -1e24");
1679 | | }
1680 | | }
1681 | | }
1682 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/DecreasePositionMarketCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract DecreasePositionMarketCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ DECREASE POSITION
10 | | // __^ __( \.__) ) GET MARKET INFO
11 | | // (@)<_____>__(_____)____/ COVERAGE
12 | |
13 | | function _checkDecreaseOrderAndGetMarketInfoCoverage(
14 | | ReaderUtils.MarketInfo memory marketInfo
15 | | ) internal {
16 | | _logMarketInfoMarketTokenCoverage_decreasePosition(
17 | | marketInfo.market.marketToken
18 | | );
19 | | _logMarketInfoIndexTokenCoverage_decreasePosition(
20 | | marketInfo.market.indexToken
21 | | );
22 | | _logMarketInfoLongTokenCoverage_decreasePosition(
23 | | marketInfo.market.longToken
24 | | );
25 | | _logMarketInfoShortTokenCoverage_decreasePosition(
26 | | marketInfo.market.shortToken
27 | | );
28 | | _logMarketInfoBorrowingFactorPerSecondForLongsCoverage_decreasePosition(
29 | | marketInfo.borrowingFactorPerSecondForLongs
30 | | );
31 | | _logMarketInfoBorrowingFactorPerSecondForShortsCoverage_decreasePosition(
32 | | marketInfo.borrowingFactorPerSecondForShorts
33 | | );
34 | | _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage_decreasePosition(
35 | | marketInfo.baseFunding.fundingFeeAmountPerSize.long
36 | | );
37 | | _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage_decreasePosition(
38 | | marketInfo.baseFunding.fundingFeeAmountPerSize.short
39 | | );
40 | | _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage_decreasePosition(
41 | | marketInfo.baseFunding.claimableFundingAmountPerSize.long
42 | | );
43 | | _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage_decreasePosition(
44 | | marketInfo.baseFunding.claimableFundingAmountPerSize.short
45 | | );
46 | | _logMarketInfoNextFundingLongsPayShortsCoverage_decreasePosition(
47 | | marketInfo.nextFunding.longsPayShorts
48 | | );
49 | | _logMarketInfoNextFundingFundingFactorPerSecondCoverage_decreasePosition(
50 | | marketInfo.nextFunding.fundingFactorPerSecond
51 | | );
52 | | _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage_decreasePosition(
53 | | marketInfo.nextFunding.nextSavedFundingFactorPerSecond
54 | | );
55 | | _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage_decreasePosition(
56 | | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.long
57 | | );
58 | | _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage_decreasePosition(
59 | | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.short
60 | | );
61 | | _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition(
62 | | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.long
63 | | );
64 | | _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition(
65 | | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.short
66 | | );
67 | | _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage_decreasePosition(
68 | | marketInfo.virtualInventory.virtualPoolAmountForLongToken
69 | | );
70 | | _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage_decreasePosition(
71 | | marketInfo.virtualInventory.virtualPoolAmountForShortToken
72 | | );
73 | | _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage_decreasePosition(
74 | | marketInfo.virtualInventory.virtualInventoryForPositions
75 | | );
76 | | _logMarketInfoIsDisabledCoverage_decreasePosition(
77 | | marketInfo.isDisabled
78 | | );
79 | | }
80 | |
81 | | function _logMarketInfoMarketTokenCoverage_decreasePosition(
82 | | address marketToken
83 | | ) internal {
84 | | if (marketToken == address(market_0_WETH_USDC)) {
85 | | fl.log("MarketInfo marketToken market_0_WETH_USDC hit");
86 | | }
87 | |
88 | | if (marketToken == address(market_WBTC_WBTC_USDC)) {
89 | | fl.log("MarketInfo marketToken market_WBTC_WBTC_USDC hit");
90 | | }
91 | | if (marketToken == address(market_WETH_WETH_USDC)) {
92 | | fl.log("MarketInfo marketToken market_WETH_WETH_USDC hit");
93 | | }
94 | | if (marketToken == address(market_WETH_WETH_USDT)) {
95 | | fl.log("MarketInfo marketToken market_WETH_WETH_USDT hit");
96 | | }
97 | | }
98 | |
99 | | function _logMarketInfoIndexTokenCoverage_decreasePosition(
100 | | address indexToken
101 | | ) internal {
102 | | if (indexToken == address(0)) {
103 | | fl.log("MarketInfo indexToken is address(0)");
104 | | } else {
105 | | fl.log("MarketInfo indexToken is non-zero address");
106 | | }
107 | | }
108 | |
109 | | function _logMarketInfoLongTokenCoverage_decreasePosition(
110 | | address longToken
111 | | ) internal {
112 | | if (longToken == address(0)) {
113 | | fl.log("MarketInfo longToken is address(0)");
114 | | } else {
115 | | fl.log("MarketInfo longToken is non-zero address");
116 | | }
117 | | }
118 | |
119 | | function _logMarketInfoShortTokenCoverage_decreasePosition(
120 | | address shortToken
121 | | ) internal {
122 | | if (shortToken == address(0)) {
123 | | fl.log("MarketInfo shortToken is address(0)");
124 | | } else {
125 | | fl.log("MarketInfo shortToken is non-zero address");
126 | | }
127 | | }
128 | |
129 | | function _logMarketInfoBorrowingFactorPerSecondForLongsCoverage_decreasePosition(
130 | | uint256 borrowingFactorPerSecondForLongs
131 | | ) internal {
132 | | if (borrowingFactorPerSecondForLongs == 0) {
133 | | fl.log("MarketInfo borrowingFactorPerSecondForLongs is 0");
134 | | }
135 | | if (
136 | | borrowingFactorPerSecondForLongs > 0 &&
137 | | borrowingFactorPerSecondForLongs <= 1e6
138 | | ) {
139 | | fl.log(
140 | | "MarketInfo borrowingFactorPerSecondForLongs is between 0 and 1e6"
141 | | );
142 | | }
143 | | if (
144 | | borrowingFactorPerSecondForLongs > 1e6 &&
145 | | borrowingFactorPerSecondForLongs <= 1e12
146 | | ) {
147 | | fl.log(
148 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e6 and 1e12"
149 | | );
150 | | }
151 | | if (
152 | | borrowingFactorPerSecondForLongs > 1e12 &&
153 | | borrowingFactorPerSecondForLongs <= 1e18
154 | | ) {
155 | | fl.log(
156 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e12 and 1e18"
157 | | );
158 | | }
159 | | if (
160 | | borrowingFactorPerSecondForLongs > 1e18 &&
161 | | borrowingFactorPerSecondForLongs <= 1e24
162 | | ) {
163 | | fl.log(
164 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e18 and 1e24"
165 | | );
166 | | }
167 | | if (borrowingFactorPerSecondForLongs > 1e24) {
168 | | fl.log(
169 | | "MarketInfo borrowingFactorPerSecondForLongs is greater than 1e24"
170 | | );
171 | | }
172 | | }
173 | |
174 | | function _logMarketInfoBorrowingFactorPerSecondForShortsCoverage_decreasePosition(
175 | | uint256 borrowingFactorPerSecondForShorts
176 | | ) internal {
177 | | if (borrowingFactorPerSecondForShorts == 0) {
178 | | fl.log("MarketInfo borrowingFactorPerSecondForShorts is 0");
179 | | }
180 | | if (
181 | | borrowingFactorPerSecondForShorts > 0 &&
182 | | borrowingFactorPerSecondForShorts <= 1e6
183 | | ) {
184 | | fl.log(
185 | | "MarketInfo borrowingFactorPerSecondForShorts is between 0 and 1e6"
186 | | );
187 | | }
188 | | if (
189 | | borrowingFactorPerSecondForShorts > 1e6 &&
190 | | borrowingFactorPerSecondForShorts <= 1e12
191 | | ) {
192 | | fl.log(
193 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e6 and 1e12"
194 | | );
195 | | }
196 | | if (
197 | | borrowingFactorPerSecondForShorts > 1e12 &&
198 | | borrowingFactorPerSecondForShorts <= 1e18
199 | | ) {
200 | | fl.log(
201 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e12 and 1e18"
202 | | );
203 | | }
204 | | if (
205 | | borrowingFactorPerSecondForShorts > 1e18 &&
206 | | borrowingFactorPerSecondForShorts <= 1e24
207 | | ) {
208 | | fl.log(
209 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e18 and 1e24"
210 | | );
211 | | }
212 | | if (borrowingFactorPerSecondForShorts > 1e24) {
213 | | fl.log(
214 | | "MarketInfo borrowingFactorPerSecondForShorts is greater than 1e24"
215 | | );
216 | | }
217 | | }
218 | |
219 | | function _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage_decreasePosition(
220 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSize
221 | | ) internal {
222 | | if (
223 | | longFundingFeeAmountPerSize.longToken == 0 &&
224 | | longFundingFeeAmountPerSize.shortToken == 0
225 | | ) {
226 | | fl.log(
227 | | "MarketInfo baseFunding longFundingFeeAmountPerSize is 0 for both longToken and shortToken"
228 | | );
229 | | }
230 | | if (
231 | | longFundingFeeAmountPerSize.longToken > 0 &&
232 | | longFundingFeeAmountPerSize.longToken <= 1e6
233 | | ) {
234 | | fl.log(
235 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 0 and 1e6"
236 | | );
237 | | }
238 | | if (
239 | | longFundingFeeAmountPerSize.longToken > 1e6 &&
240 | | longFundingFeeAmountPerSize.longToken <= 1e12
241 | | ) {
242 | | fl.log(
243 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e6 and 1e12"
244 | | );
245 | | }
246 | | if (
247 | | longFundingFeeAmountPerSize.longToken > 1e12 &&
248 | | longFundingFeeAmountPerSize.longToken <= 1e18
249 | | ) {
250 | | fl.log(
251 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e12 and 1e18"
252 | | );
253 | | }
254 | | if (
255 | | longFundingFeeAmountPerSize.longToken > 1e18 &&
256 | | longFundingFeeAmountPerSize.longToken <= 1e24
257 | | ) {
258 | | fl.log(
259 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e18 and 1e24"
260 | | );
261 | | }
262 | | if (longFundingFeeAmountPerSize.longToken > 1e24) {
263 | | fl.log(
264 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is greater than 1e24"
265 | | );
266 | | }
267 | | if (
268 | | longFundingFeeAmountPerSize.shortToken > 0 &&
269 | | longFundingFeeAmountPerSize.shortToken <= 1e6
270 | | ) {
271 | | fl.log(
272 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 0 and 1e6"
273 | | );
274 | | }
275 | | if (
276 | | longFundingFeeAmountPerSize.shortToken > 1e6 &&
277 | | longFundingFeeAmountPerSize.shortToken <= 1e12
278 | | ) {
279 | | fl.log(
280 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e6 and 1e12"
281 | | );
282 | | }
283 | | if (
284 | | longFundingFeeAmountPerSize.shortToken > 1e12 &&
285 | | longFundingFeeAmountPerSize.shortToken <= 1e18
286 | | ) {
287 | | fl.log(
288 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e12 and 1e18"
289 | | );
290 | | }
291 | | if (
292 | | longFundingFeeAmountPerSize.shortToken > 1e18 &&
293 | | longFundingFeeAmountPerSize.shortToken <= 1e24
294 | | ) {
295 | | fl.log(
296 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e18 and 1e24"
297 | | );
298 | | }
299 | | if (longFundingFeeAmountPerSize.shortToken > 1e24) {
300 | | fl.log(
301 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is greater than 1e24"
302 | | );
303 | | }
304 | | }
305 | |
306 | | function _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage_decreasePosition(
307 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSize
308 | | ) internal {
309 | | if (
310 | | shortFundingFeeAmountPerSize.longToken == 0 &&
311 | | shortFundingFeeAmountPerSize.shortToken == 0
312 | | ) {
313 | | fl.log(
314 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize is 0 for both longToken and shortToken"
315 | | );
316 | | }
317 | | if (
318 | | shortFundingFeeAmountPerSize.longToken > 0 &&
319 | | shortFundingFeeAmountPerSize.longToken <= 1e6
320 | | ) {
321 | | fl.log(
322 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 0 and 1e6"
323 | | );
324 | | }
325 | | if (
326 | | shortFundingFeeAmountPerSize.longToken > 1e6 &&
327 | | shortFundingFeeAmountPerSize.longToken <= 1e12
328 | | ) {
329 | | fl.log(
330 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e6 and 1e12"
331 | | );
332 | | }
333 | | if (
334 | | shortFundingFeeAmountPerSize.longToken > 1e12 &&
335 | | shortFundingFeeAmountPerSize.longToken <= 1e18
336 | | ) {
337 | | fl.log(
338 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e12 and 1e18"
339 | | );
340 | | }
341 | | if (
342 | | shortFundingFeeAmountPerSize.longToken > 1e18 &&
343 | | shortFundingFeeAmountPerSize.longToken <= 1e24
344 | | ) {
345 | | fl.log(
346 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e18 and 1e24"
347 | | );
348 | | }
349 | | if (shortFundingFeeAmountPerSize.longToken > 1e24) {
350 | | fl.log(
351 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is greater than 1e24"
352 | | );
353 | | }
354 | | if (
355 | | shortFundingFeeAmountPerSize.shortToken > 0 &&
356 | | shortFundingFeeAmountPerSize.shortToken <= 1e6
357 | | ) {
358 | | fl.log(
359 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 0 and 1e6"
360 | | );
361 | | }
362 | | if (
363 | | shortFundingFeeAmountPerSize.shortToken > 1e6 &&
364 | | shortFundingFeeAmountPerSize.shortToken <= 1e12
365 | | ) {
366 | | fl.log(
367 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e6 and 1e12"
368 | | );
369 | | }
370 | | if (
371 | | shortFundingFeeAmountPerSize.shortToken > 1e12 &&
372 | | shortFundingFeeAmountPerSize.shortToken <= 1e18
373 | | ) {
374 | | fl.log(
375 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e12 and 1e18"
376 | | );
377 | | }
378 | | if (
379 | | shortFundingFeeAmountPerSize.shortToken > 1e18 &&
380 | | shortFundingFeeAmountPerSize.shortToken <= 1e24
381 | | ) {
382 | | fl.log(
383 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e18 and 1e24"
384 | | );
385 | | }
386 | | if (shortFundingFeeAmountPerSize.shortToken > 1e24) {
387 | | fl.log(
388 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is greater than 1e24"
389 | | );
390 | | }
391 | | }
392 | |
393 | | function _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage_decreasePosition(
394 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSize
395 | | ) internal {
396 | | if (
397 | | longClaimableFundingAmountPerSize.longToken == 0 &&
398 | | longClaimableFundingAmountPerSize.shortToken == 0
399 | | ) {
400 | | fl.log(
401 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize is 0 for both longToken and shortToken"
402 | | );
403 | | }
404 | | if (
405 | | longClaimableFundingAmountPerSize.longToken > 0 &&
406 | | longClaimableFundingAmountPerSize.longToken <= 1e6
407 | | ) {
408 | | fl.log(
409 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 0 and 1e6"
410 | | );
411 | | }
412 | | if (
413 | | longClaimableFundingAmountPerSize.longToken > 1e6 &&
414 | | longClaimableFundingAmountPerSize.longToken <= 1e12
415 | | ) {
416 | | fl.log(
417 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e6 and 1e12"
418 | | );
419 | | }
420 | | if (
421 | | longClaimableFundingAmountPerSize.longToken > 1e12 &&
422 | | longClaimableFundingAmountPerSize.longToken <= 1e18
423 | | ) {
424 | | fl.log(
425 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e12 and 1e18"
426 | | );
427 | | }
428 | | if (
429 | | longClaimableFundingAmountPerSize.longToken > 1e18 &&
430 | | longClaimableFundingAmountPerSize.longToken <= 1e24
431 | | ) {
432 | | fl.log(
433 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e18 and 1e24"
434 | | );
435 | | }
436 | | if (longClaimableFundingAmountPerSize.longToken > 1e24) {
437 | | fl.log(
438 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is greater than 1e24"
439 | | );
440 | | }
441 | | if (
442 | | longClaimableFundingAmountPerSize.shortToken > 0 &&
443 | | longClaimableFundingAmountPerSize.shortToken <= 1e6
444 | | ) {
445 | | fl.log(
446 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 0 and 1e6"
447 | | );
448 | | }
449 | | if (
450 | | longClaimableFundingAmountPerSize.shortToken > 1e6 &&
451 | | longClaimableFundingAmountPerSize.shortToken <= 1e12
452 | | ) {
453 | | fl.log(
454 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12"
455 | | );
456 | | }
457 | | if (
458 | | longClaimableFundingAmountPerSize.shortToken > 1e12 &&
459 | | longClaimableFundingAmountPerSize.shortToken <= 1e18
460 | | ) {
461 | | fl.log(
462 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18"
463 | | );
464 | | }
465 | | if (
466 | | longClaimableFundingAmountPerSize.shortToken > 1e18 &&
467 | | longClaimableFundingAmountPerSize.shortToken <= 1e24
468 | | ) {
469 | | fl.log(
470 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24"
471 | | );
472 | | }
473 | | if (longClaimableFundingAmountPerSize.shortToken > 1e24) {
474 | | fl.log(
475 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is greater than 1e24"
476 | | );
477 | | }
478 | | }
479 | |
480 | | function _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage_decreasePosition(
481 | | MarketUtils.CollateralType memory shortClaimableFundingAmountPerSize
482 | | ) internal {
483 | | if (
484 | | shortClaimableFundingAmountPerSize.longToken == 0 &&
485 | | shortClaimableFundingAmountPerSize.shortToken == 0
486 | | ) {
487 | | fl.log(
488 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize is 0 for both longToken and shortToken"
489 | | );
490 | | }
491 | | if (
492 | | shortClaimableFundingAmountPerSize.longToken > 0 &&
493 | | shortClaimableFundingAmountPerSize.longToken <= 1e6
494 | | ) {
495 | | fl.log(
496 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 0 and 1e6"
497 | | );
498 | | }
499 | | if (
500 | | shortClaimableFundingAmountPerSize.longToken > 1e6 &&
501 | | shortClaimableFundingAmountPerSize.longToken <= 1e12
502 | | ) {
503 | | fl.log(
504 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e6 and 1e12"
505 | | );
506 | | }
507 | | if (
508 | | shortClaimableFundingAmountPerSize.longToken > 1e12 &&
509 | | shortClaimableFundingAmountPerSize.longToken <= 1e18
510 | | ) {
511 | | fl.log(
512 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e12 and 1e18"
513 | | );
514 | | }
515 | | if (
516 | | shortClaimableFundingAmountPerSize.longToken > 1e18 &&
517 | | shortClaimableFundingAmountPerSize.longToken <= 1e24
518 | | ) {
519 | | fl.log(
520 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e18 and 1e24"
521 | | );
522 | | }
523 | | if (shortClaimableFundingAmountPerSize.longToken > 1e24) {
524 | | fl.log(
525 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is greater than 1e24"
526 | | );
527 | | }
528 | | if (
529 | | shortClaimableFundingAmountPerSize.shortToken > 0 &&
530 | | shortClaimableFundingAmountPerSize.shortToken <= 1e6
531 | | ) {
532 | | fl.log(
533 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 0 and 1e6"
534 | | );
535 | | }
536 | | if (
537 | | shortClaimableFundingAmountPerSize.shortToken > 1e6 &&
538 | | shortClaimableFundingAmountPerSize.shortToken <= 1e12
539 | | ) {
540 | | fl.log(
541 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12"
542 | | );
543 | | }
544 | | if (
545 | | shortClaimableFundingAmountPerSize.shortToken > 1e12 &&
546 | | shortClaimableFundingAmountPerSize.shortToken <= 1e18
547 | | ) {
548 | | fl.log(
549 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18"
550 | | );
551 | | }
552 | | if (
553 | | shortClaimableFundingAmountPerSize.shortToken > 1e18 &&
554 | | shortClaimableFundingAmountPerSize.shortToken <= 1e24
555 | | ) {
556 | | fl.log(
557 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24"
558 | | );
559 | | }
560 | | if (shortClaimableFundingAmountPerSize.shortToken > 1e24) {
561 | | fl.log(
562 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is greater than 1e24"
563 | | );
564 | | }
565 | | }
566 | |
567 | | function _logMarketInfoNextFundingLongsPayShortsCoverage_decreasePosition(
568 | | bool longsPayShorts
569 | | ) internal {
570 | | if (longsPayShorts) {
571 | | fl.log("MarketInfo nextFunding longsPayShorts is true");
572 | | } else {
573 | | fl.log("MarketInfo nextFunding longsPayShorts is false");
574 | | }
575 | | }
576 | |
577 | | function _logMarketInfoNextFundingFundingFactorPerSecondCoverage_decreasePosition(
578 | | uint256 fundingFactorPerSecond
579 | | ) internal {
580 | | if (fundingFactorPerSecond == 0) {
581 | | fl.log("MarketInfo nextFunding fundingFactorPerSecond is 0");
582 | | }
583 | | if (fundingFactorPerSecond > 0 && fundingFactorPerSecond <= 1e6) {
584 | | fl.log(
585 | | "MarketInfo nextFunding fundingFactorPerSecond is between 0 and 1e6"
586 | | );
587 | | }
588 | | if (fundingFactorPerSecond > 1e6 && fundingFactorPerSecond <= 1e12) {
589 | | fl.log(
590 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e6 and 1e12"
591 | | );
592 | | }
593 | | if (fundingFactorPerSecond > 1e12 && fundingFactorPerSecond <= 1e18) {
594 | | fl.log(
595 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e12 and 1e18"
596 | | );
597 | | }
598 | | if (fundingFactorPerSecond > 1e18 && fundingFactorPerSecond <= 1e24) {
599 | | fl.log(
600 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e18 and 1e24"
601 | | );
602 | | }
603 | | if (fundingFactorPerSecond > 1e24) {
604 | | fl.log(
605 | | "MarketInfo nextFunding fundingFactorPerSecond is greater than 1e24"
606 | | );
607 | | }
608 | | }
609 | |
610 | | function _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage_decreasePosition(
611 | | int256 nextSavedFundingFactorPerSecond
612 | | ) internal {
613 | | if (nextSavedFundingFactorPerSecond == 0) {
614 | | fl.log(
615 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is 0"
616 | | );
617 | | }
618 | | if (
619 | | nextSavedFundingFactorPerSecond > 0 &&
620 | | nextSavedFundingFactorPerSecond <= 1e6
621 | | ) {
622 | | fl.log(
623 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and 1e6"
624 | | );
625 | | }
626 | | if (
627 | | nextSavedFundingFactorPerSecond > 1e6 &&
628 | | nextSavedFundingFactorPerSecond <= 1e12
629 | | ) {
630 | | fl.log(
631 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e6 and 1e12"
632 | | );
633 | | }
634 | | if (
635 | | nextSavedFundingFactorPerSecond > 1e12 &&
636 | | nextSavedFundingFactorPerSecond <= 1e18
637 | | ) {
638 | | fl.log(
639 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e12 and 1e18"
640 | | );
641 | | }
642 | | if (
643 | | nextSavedFundingFactorPerSecond > 1e18 &&
644 | | nextSavedFundingFactorPerSecond <= 1e24
645 | | ) {
646 | | fl.log(
647 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e18 and 1e24"
648 | | );
649 | | }
650 | | if (nextSavedFundingFactorPerSecond > 1e24) {
651 | | fl.log(
652 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is greater than 1e24"
653 | | );
654 | | }
655 | | if (
656 | | nextSavedFundingFactorPerSecond < 0 &&
657 | | nextSavedFundingFactorPerSecond >= -1e6
658 | | ) {
659 | | fl.log(
660 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and -1e6"
661 | | );
662 | | }
663 | | if (
664 | | nextSavedFundingFactorPerSecond < -1e6 &&
665 | | nextSavedFundingFactorPerSecond >= -1e12
666 | | ) {
667 | | fl.log(
668 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e6 and -1e12"
669 | | );
670 | | }
671 | | if (
672 | | nextSavedFundingFactorPerSecond < -1e12 &&
673 | | nextSavedFundingFactorPerSecond >= -1e18
674 | | ) {
675 | | fl.log(
676 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e12 and -1e18"
677 | | );
678 | | }
679 | | if (
680 | | nextSavedFundingFactorPerSecond < -1e18 &&
681 | | nextSavedFundingFactorPerSecond >= -1e24
682 | | ) {
683 | | fl.log(
684 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e18 and -1e24"
685 | | );
686 | | }
687 | | if (nextSavedFundingFactorPerSecond < -1e24) {
688 | | fl.log(
689 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is less than -1e24"
690 | | );
691 | | }
692 | | }
693 | |
694 | | function _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage_decreasePosition(
695 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSizeDelta
696 | | ) internal {
697 | | if (
698 | | longFundingFeeAmountPerSizeDelta.longToken == 0 &&
699 | | longFundingFeeAmountPerSizeDelta.shortToken == 0
700 | | ) {
701 | | fl.log(
702 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken"
703 | | );
704 | | }
705 | | if (
706 | | longFundingFeeAmountPerSizeDelta.longToken > 0 &&
707 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e6
708 | | ) {
709 | | fl.log(
710 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6"
711 | | );
712 | | }
713 | | if (
714 | | longFundingFeeAmountPerSizeDelta.longToken > 1e6 &&
715 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e12
716 | | ) {
717 | | fl.log(
718 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12"
719 | | );
720 | | }
721 | | if (
722 | | longFundingFeeAmountPerSizeDelta.longToken > 1e12 &&
723 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e18
724 | | ) {
725 | | fl.log(
726 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18"
727 | | );
728 | | }
729 | | if (
730 | | longFundingFeeAmountPerSizeDelta.longToken > 1e18 &&
731 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e24
732 | | ) {
733 | | fl.log(
734 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24"
735 | | );
736 | | }
737 | | if (longFundingFeeAmountPerSizeDelta.longToken > 1e24) {
738 | | fl.log(
739 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is greater than 1e24"
740 | | );
741 | | }
742 | | if (
743 | | longFundingFeeAmountPerSizeDelta.shortToken > 0 &&
744 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e6
745 | | ) {
746 | | fl.log(
747 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6"
748 | | );
749 | | }
750 | | if (
751 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e6 &&
752 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e12
753 | | ) {
754 | | fl.log(
755 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12"
756 | | );
757 | | }
758 | | if (
759 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e12 &&
760 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e18
761 | | ) {
762 | | fl.log(
763 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18"
764 | | );
765 | | }
766 | | if (
767 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e18 &&
768 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e24
769 | | ) {
770 | | fl.log(
771 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24"
772 | | );
773 | | }
774 | | if (longFundingFeeAmountPerSizeDelta.shortToken > 1e24) {
775 | | fl.log(
776 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is greater than 1e24"
777 | | );
778 | | }
779 | | }
780 | | function _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage_decreasePosition(
781 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSizeDelta
782 | | ) internal {
783 | | if (
784 | | shortFundingFeeAmountPerSizeDelta.longToken == 0 &&
785 | | shortFundingFeeAmountPerSizeDelta.shortToken == 0
786 | | ) {
787 | | fl.log(
788 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken"
789 | | );
790 | | }
791 | | if (
792 | | shortFundingFeeAmountPerSizeDelta.longToken > 0 &&
793 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e6
794 | | ) {
795 | | fl.log(
796 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6"
797 | | );
798 | | }
799 | | if (
800 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e6 &&
801 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e12
802 | | ) {
803 | | fl.log(
804 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12"
805 | | );
806 | | }
807 | | if (
808 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e12 &&
809 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e18
810 | | ) {
811 | | fl.log(
812 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18"
813 | | );
814 | | }
815 | | if (
816 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e18 &&
817 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e24
818 | | ) {
819 | | fl.log(
820 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24"
821 | | );
822 | | }
823 | | if (shortFundingFeeAmountPerSizeDelta.longToken > 1e24) {
824 | | fl.log(
825 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is greater than 1e24"
826 | | );
827 | | }
828 | | if (
829 | | shortFundingFeeAmountPerSizeDelta.shortToken > 0 &&
830 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e6
831 | | ) {
832 | | fl.log(
833 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6"
834 | | );
835 | | }
836 | | if (
837 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e6 &&
838 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e12
839 | | ) {
840 | | fl.log(
841 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12"
842 | | );
843 | | }
844 | | if (
845 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e12 &&
846 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e18
847 | | ) {
848 | | fl.log(
849 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18"
850 | | );
851 | | }
852 | | if (
853 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e18 &&
854 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e24
855 | | ) {
856 | | fl.log(
857 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24"
858 | | );
859 | | }
860 | | if (shortFundingFeeAmountPerSizeDelta.shortToken > 1e24) {
861 | | fl.log(
862 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is greater than 1e24"
863 | | );
864 | | }
865 | | }
866 | |
867 | | function _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition(
868 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSizeDelta
869 | | ) internal {
870 | | if (
871 | | longClaimableFundingAmountPerSizeDelta.longToken == 0 &&
872 | | longClaimableFundingAmountPerSizeDelta.shortToken == 0
873 | | ) {
874 | | fl.log(
875 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken"
876 | | );
877 | | }
878 | | if (
879 | | longClaimableFundingAmountPerSizeDelta.longToken > 0 &&
880 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e6
881 | | ) {
882 | | fl.log(
883 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6"
884 | | );
885 | | }
886 | | if (
887 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e6 &&
888 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e12
889 | | ) {
890 | | fl.log(
891 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12"
892 | | );
893 | | }
894 | | if (
895 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e12 &&
896 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e18
897 | | ) {
898 | | fl.log(
899 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18"
900 | | );
901 | | }
902 | | if (
903 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e18 &&
904 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e24
905 | | ) {
906 | | fl.log(
907 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24"
908 | | );
909 | | }
910 | | if (longClaimableFundingAmountPerSizeDelta.longToken > 1e24) {
911 | | fl.log(
912 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is greater than 1e24"
913 | | );
914 | | }
915 | | if (
916 | | longClaimableFundingAmountPerSizeDelta.shortToken > 0 &&
917 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e6
918 | | ) {
919 | | fl.log(
920 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6"
921 | | );
922 | | }
923 | | if (
924 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e6 &&
925 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e12
926 | | ) {
927 | | fl.log(
928 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12"
929 | | );
930 | | }
931 | | if (
932 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e12 &&
933 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e18
934 | | ) {
935 | | fl.log(
936 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18"
937 | | );
938 | | }
939 | | if (
940 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e18 &&
941 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e24
942 | | ) {
943 | | fl.log(
944 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24"
945 | | );
946 | | }
947 | | if (longClaimableFundingAmountPerSizeDelta.shortToken > 1e24) {
948 | | fl.log(
949 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24"
950 | | );
951 | | }
952 | | }
953 | |
954 | | function _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition(
955 | | MarketUtils.CollateralType
956 | | memory shortClaimableFundingAmountPerSizeDelta
957 | | ) internal {
958 | | if (
959 | | shortClaimableFundingAmountPerSizeDelta.longToken == 0 &&
960 | | shortClaimableFundingAmountPerSizeDelta.shortToken == 0
961 | | ) {
962 | | fl.log(
963 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken"
964 | | );
965 | | }
966 | | if (
967 | | shortClaimableFundingAmountPerSizeDelta.longToken > 0 &&
968 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e6
969 | | ) {
970 | | fl.log(
971 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6"
972 | | );
973 | | }
974 | | if (
975 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e6 &&
976 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e12
977 | | ) {
978 | | fl.log(
979 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12"
980 | | );
981 | | }
982 | | if (
983 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e12 &&
984 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e18
985 | | ) {
986 | | fl.log(
987 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18"
988 | | );
989 | | }
990 | | if (
991 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e18 &&
992 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e24
993 | | ) {
994 | | fl.log(
995 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24"
996 | | );
997 | | }
998 | | if (shortClaimableFundingAmountPerSizeDelta.longToken > 1e24) {
999 | | fl.log(
1000 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is greater than 1e24"
1001 | | );
1002 | | }
1003 | | if (
1004 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 0 &&
1005 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e6
1006 | | ) {
1007 | | fl.log(
1008 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6"
1009 | | );
1010 | | }
1011 | | if (
1012 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e6 &&
1013 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e12
1014 | | ) {
1015 | | fl.log(
1016 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12"
1017 | | );
1018 | | }
1019 | | if (
1020 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e12 &&
1021 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e18
1022 | | ) {
1023 | | fl.log(
1024 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18"
1025 | | );
1026 | | }
1027 | | if (
1028 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e18 &&
1029 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e24
1030 | | ) {
1031 | | fl.log(
1032 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24"
1033 | | );
1034 | | }
1035 | | if (shortClaimableFundingAmountPerSizeDelta.shortToken > 1e24) {
1036 | | fl.log(
1037 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24"
1038 | | );
1039 | | }
1040 | | }
1041 | |
1042 | | function _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage_decreasePosition(
1043 | | uint256 virtualPoolAmountForLongToken
1044 | | ) internal {
1045 | | if (virtualPoolAmountForLongToken == 0) {
1046 | | fl.log(
1047 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is 0"
1048 | | );
1049 | | }
1050 | | if (
1051 | | virtualPoolAmountForLongToken > 0 &&
1052 | | virtualPoolAmountForLongToken <= 1e6
1053 | | ) {
1054 | | fl.log(
1055 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 0 and 1e6"
1056 | | );
1057 | | }
1058 | | if (
1059 | | virtualPoolAmountForLongToken > 1e6 &&
1060 | | virtualPoolAmountForLongToken <= 1e12
1061 | | ) {
1062 | | fl.log(
1063 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e6 and 1e12"
1064 | | );
1065 | | }
1066 | | if (
1067 | | virtualPoolAmountForLongToken > 1e12 &&
1068 | | virtualPoolAmountForLongToken <= 1e18
1069 | | ) {
1070 | | fl.log(
1071 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e12 and 1e18"
1072 | | );
1073 | | }
1074 | | if (
1075 | | virtualPoolAmountForLongToken > 1e18 &&
1076 | | virtualPoolAmountForLongToken <= 1e24
1077 | | ) {
1078 | | fl.log(
1079 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e18 and 1e24"
1080 | | );
1081 | | }
1082 | | if (virtualPoolAmountForLongToken > 1e24) {
1083 | | fl.log(
1084 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is greater than 1e24"
1085 | | );
1086 | | }
1087 | | }
1088 | |
1089 | | function _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage_decreasePosition(
1090 | | uint256 virtualPoolAmountForShortToken
1091 | | ) internal {
1092 | | if (virtualPoolAmountForShortToken == 0) {
1093 | | fl.log(
1094 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is 0"
1095 | | );
1096 | | }
1097 | | if (
1098 | | virtualPoolAmountForShortToken > 0 &&
1099 | | virtualPoolAmountForShortToken <= 1e6
1100 | | ) {
1101 | | fl.log(
1102 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 0 and 1e6"
1103 | | );
1104 | | }
1105 | | if (
1106 | | virtualPoolAmountForShortToken > 1e6 &&
1107 | | virtualPoolAmountForShortToken <= 1e12
1108 | | ) {
1109 | | fl.log(
1110 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e6 and 1e12"
1111 | | );
1112 | | }
1113 | | if (
1114 | | virtualPoolAmountForShortToken > 1e12 &&
1115 | | virtualPoolAmountForShortToken <= 1e18
1116 | | ) {
1117 | | fl.log(
1118 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e12 and 1e18"
1119 | | );
1120 | | }
1121 | | if (
1122 | | virtualPoolAmountForShortToken > 1e18 &&
1123 | | virtualPoolAmountForShortToken <= 1e24
1124 | | ) {
1125 | | fl.log(
1126 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e18 and 1e24"
1127 | | );
1128 | | }
1129 | | if (virtualPoolAmountForShortToken > 1e24) {
1130 | | fl.log(
1131 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is greater than 1e24"
1132 | | );
1133 | | }
1134 | | }
1135 | |
1136 | | function _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage_decreasePosition(
1137 | | int256 virtualInventoryForPositions
1138 | | ) internal {
1139 | | if (virtualInventoryForPositions == 0) {
1140 | | fl.log(
1141 | | "MarketInfo virtualInventory virtualInventoryForPositions is 0"
1142 | | );
1143 | | }
1144 | | if (
1145 | | virtualInventoryForPositions > 0 &&
1146 | | virtualInventoryForPositions <= 1e6
1147 | | ) {
1148 | | fl.log(
1149 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and 1e6"
1150 | | );
1151 | | }
1152 | | if (
1153 | | virtualInventoryForPositions > 1e6 &&
1154 | | virtualInventoryForPositions <= 1e12
1155 | | ) {
1156 | | fl.log(
1157 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e6 and 1e12"
1158 | | );
1159 | | }
1160 | | if (
1161 | | virtualInventoryForPositions > 1e12 &&
1162 | | virtualInventoryForPositions <= 1e18
1163 | | ) {
1164 | | fl.log(
1165 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e12 and 1e18"
1166 | | );
1167 | | }
1168 | | if (
1169 | | virtualInventoryForPositions > 1e18 &&
1170 | | virtualInventoryForPositions <= 1e24
1171 | | ) {
1172 | | fl.log(
1173 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e18 and 1e24"
1174 | | );
1175 | | }
1176 | | if (virtualInventoryForPositions > 1e24) {
1177 | | fl.log(
1178 | | "MarketInfo virtualInventory virtualInventoryForPositions is greater than 1e24"
1179 | | );
1180 | | }
1181 | | if (
1182 | | virtualInventoryForPositions < 0 &&
1183 | | virtualInventoryForPositions >= -1e6
1184 | | ) {
1185 | | fl.log(
1186 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and -1e6"
1187 | | );
1188 | | }
1189 | | if (
1190 | | virtualInventoryForPositions < -1e6 &&
1191 | | virtualInventoryForPositions >= -1e12
1192 | | ) {
1193 | | fl.log(
1194 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e6 and -1e12"
1195 | | );
1196 | | }
1197 | | if (
1198 | | virtualInventoryForPositions < -1e12 &&
1199 | | virtualInventoryForPositions >= -1e18
1200 | | ) {
1201 | | fl.log(
1202 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e12 and -1e18"
1203 | | );
1204 | | }
1205 | | if (
1206 | | virtualInventoryForPositions < -1e18 &&
1207 | | virtualInventoryForPositions >= -1e24
1208 | | ) {
1209 | | fl.log(
1210 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e18 and -1e24"
1211 | | );
1212 | | }
1213 | | if (virtualInventoryForPositions < -1e24) {
1214 | | fl.log(
1215 | | "MarketInfo virtualInventory virtualInventoryForPositions is less than -1e24"
1216 | | );
1217 | | }
1218 | | }
1219 | |
1220 | | function _logMarketInfoIsDisabledCoverage_decreasePosition(
1221 | | bool isDisabled
1222 | | ) internal {
1223 | | if (isDisabled) {
1224 | | fl.log("MarketInfo isDisabled is true");
1225 | | } else {
1226 | | fl.log("MarketInfo isDisabled is false");
1227 | | }
1228 | | }
1229 | | }
1230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/IncreasePositionInfoCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract IncreasePositionInfoCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ INCREASE POSITION
10 | | // __^ __( \.__) ) GET POSITION INFO
11 | | // (@)<_____>__(_____)____/ COVERAGE
12 | |
13 | * | function _checkIncreaseOrderAndGetPositionCoverage(
14 | | Position.Props memory position
15 | | ) internal {
16 | * | _logPositionAccountCoverage(position.addresses.account);
17 | * | _logPositionMarketCoverage(position.addresses.market);
18 | * | _logPositionCollateralTokenCoverage(position.addresses.collateralToken);
19 | * | _logPositionSizeInUsdCoverage(position.numbers.sizeInUsd);
20 | * | _logPositionSizeInTokensCoverage(position.numbers.sizeInTokens);
21 | * | _logPositionCollateralAmountCoverage(position.numbers.collateralAmount);
22 | * | _logPositionBorrowingFactorCoverage(position.numbers.borrowingFactor);
23 | * | _logPositionFundingFeeAmountPerSizeCoverage(
24 | * | position.numbers.fundingFeeAmountPerSize
25 | | );
26 | * | _logPositionLongTokenClaimableFundingAmountPerSizeCoverage(
27 | * | position.numbers.longTokenClaimableFundingAmountPerSize
28 | | );
29 | * | _logPositionShortTokenClaimableFundingAmountPerSizeCoverage(
30 | * | position.numbers.shortTokenClaimableFundingAmountPerSize
31 | | );
32 | * | _logPositionIncreasedAtBlockCoverage(position.numbers.increasedAtBlock);
33 | * | _logPositionDecreasedAtBlockCoverage(position.numbers.decreasedAtBlock);
34 | * | _logPositionIncreasedAtTimeCoverage(position.numbers.increasedAtTime);
35 | * | _logPositionDecreasedAtTimeCoverage(position.numbers.decreasedAtTime);
36 | * | _logPositionIsLongCoverage(position.flags.isLong);
37 | | }
38 | |
39 | * | function _checkIncreaseOrderAndGetPositionInfoCoverage(
40 | | ReaderUtils.PositionInfo memory positionInfo
41 | | ) internal {
42 | | // Position.Props logged above
43 | * | _logPositionFeesReferralCodeCoverage(
44 | * | positionInfo.fees.referral.referralCode
45 | | );
46 | * | _logPositionFeesAffiliateCoverage(positionInfo.fees.referral.affiliate);
47 | * | _logPositionFeesTraderCoverage(positionInfo.fees.referral.trader);
48 | * | _logPositionFeesTotalRebateFactorCoverage(
49 | * | positionInfo.fees.referral.totalRebateFactor
50 | | );
51 | * | _logPositionFeesTraderDiscountFactorCoverage(
52 | * | positionInfo.fees.referral.traderDiscountFactor
53 | | );
54 | * | _logPositionFeesTotalRebateAmountCoverage(
55 | * | positionInfo.fees.referral.totalRebateAmount
56 | | );
57 | * | _logPositionFeesTraderDiscountAmountCoverage(
58 | * | positionInfo.fees.referral.traderDiscountAmount
59 | | );
60 | * | _logPositionFeesAffiliateRewardAmountCoverage(
61 | * | positionInfo.fees.referral.affiliateRewardAmount
62 | | );
63 | * | _logPositionFeesFundingFeeAmountCoverage(
64 | * | positionInfo.fees.funding.fundingFeeAmount
65 | | );
66 | * | _logPositionFeesClaimableLongTokenAmountCoverage(
67 | * | positionInfo.fees.funding.claimableLongTokenAmount
68 | | );
69 | * | _logPositionFeesClaimableShortTokenAmountCoverage(
70 | * | positionInfo.fees.funding.claimableShortTokenAmount
71 | | );
72 | * | _logPositionFeesLatestFundingFeeAmountPerSizeCoverage(
73 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize
74 | | );
75 | * | _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage(
76 | * | positionInfo
77 | | .fees
78 | | .funding
79 | | .latestLongTokenClaimableFundingAmountPerSize
80 | | );
81 | * | _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage(
82 | * | positionInfo
83 | | .fees
84 | | .funding
85 | | .latestShortTokenClaimableFundingAmountPerSize
86 | | );
87 | * | _logPositionFeesBorrowingFeeUsdCoverage(
88 | * | positionInfo.fees.borrowing.borrowingFeeUsd
89 | | );
90 | * | _logPositionFeesBorrowingFeeAmountCoverage(
91 | * | positionInfo.fees.borrowing.borrowingFeeAmount
92 | | );
93 | * | _logPositionFeesBorrowingFeeReceiverFactorCoverage(
94 | * | positionInfo.fees.borrowing.borrowingFeeReceiverFactor
95 | | );
96 | * | _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage(
97 | * | positionInfo.fees.borrowing.borrowingFeeAmountForFeeReceiver
98 | | );
99 | * | _logPositionFeesUiFeeReceiverCoverage(
100 | * | positionInfo.fees.ui.uiFeeReceiver
101 | | );
102 | * | _logPositionFeesUiFeeReceiverFactorCoverage(
103 | * | positionInfo.fees.ui.uiFeeReceiverFactor
104 | | );
105 | * | _logPositionFeesUiFeeAmountCoverage(positionInfo.fees.ui.uiFeeAmount);
106 | * | _logPositionFeesCollateralTokenPriceCoverage(
107 | * | positionInfo.fees.collateralTokenPrice.max
108 | | );
109 | * | _logPositionFeesPositionFeeFactorCoverage(
110 | * | positionInfo.fees.positionFeeFactor
111 | | );
112 | * | _logPositionFeesProtocolFeeAmountCoverage(
113 | * | positionInfo.fees.protocolFeeAmount
114 | | );
115 | * | _logPositionFeesPositionFeeReceiverFactorCoverage(
116 | * | positionInfo.fees.positionFeeReceiverFactor
117 | | );
118 | * | _logPositionFeesFeeReceiverAmountCoverage(
119 | * | positionInfo.fees.feeReceiverAmount
120 | | );
121 | * | _logPositionFeesFeeAmountForPoolCoverage(
122 | * | positionInfo.fees.feeAmountForPool
123 | | );
124 | * | _logPositionFeesPositionFeeAmountForPoolCoverage(
125 | * | positionInfo.fees.positionFeeAmountForPool
126 | | );
127 | * | _logPositionFeesPositionFeeAmountCoverage(
128 | * | positionInfo.fees.positionFeeAmount
129 | | );
130 | * | _logPositionFeesTotalCostAmountExcludingFundingCoverage(
131 | * | positionInfo.fees.totalCostAmountExcludingFunding
132 | | );
133 | * | _logPositionFeesTotalCostAmountCoverage(
134 | * | positionInfo.fees.totalCostAmount
135 | | );
136 | |
137 | | // ExecutionPriceResult
138 | * | _logExecutionPriceResultPriceImpactUsdCoverage(
139 | * | positionInfo.executionPriceResult.priceImpactUsd
140 | | );
141 | * | _logExecutionPriceResultPriceImpactDiffUsdCoverage(
142 | * | positionInfo.executionPriceResult.priceImpactDiffUsd
143 | | );
144 | * | _logExecutionPriceResultExecutionPriceCoverage(
145 | * | positionInfo.executionPriceResult.executionPrice
146 | | );
147 | |
148 | * | _logPositionInfoBasePnlUsdCoverage(positionInfo.basePnlUsd);
149 | * | _logPositionInfoUncappedBasePnlUsdCoverage(
150 | * | positionInfo.uncappedBasePnlUsd
151 | | );
152 | * | _logPositionInfoPnlAfterPriceImpactUsdCoverage(
153 | * | positionInfo.pnlAfterPriceImpactUsd
154 | | );
155 | | }
156 | |
157 | * | function _logPositionAccountCoverage(address account) internal {
158 | * | if (account == USER0) {
159 | * | fl.log("PositionFees account USER0 hit");
160 | | }
161 | * | if (account == USER1) {
162 | * | fl.log("PositionFees account USER1 hit");
163 | | }
164 | * | if (account == USER2) {
165 | * | fl.log("PositionFees account USER2 hit");
166 | | }
167 | * | if (account == USER3) {
168 | * | fl.log("PositionFees account USER3 hit");
169 | | }
170 | * | if (account == USER4) {
171 | * | fl.log("PositionFees account USER4 hit");
172 | | }
173 | * | if (account == USER5) {
174 | * | fl.log("PositionFees account USER5 hit");
175 | | }
176 | * | if (account == USER6) {
177 | * | fl.log("PositionFees account USER6 hit");
178 | | }
179 | * | if (account == USER7) {
180 | * | fl.log("PositionFees account USER7 hit");
181 | | }
182 | * | if (account == USER8) {
183 | * | fl.log("PositionFees account USER8 hit");
184 | | }
185 | * | if (account == USER9) {
186 | * | fl.log("PositionFees account USER9 hit");
187 | | }
188 | * | if (account == USER10) {
189 | * | fl.log("PositionFees account USER10 hit");
190 | | }
191 | * | if (account == USER11) {
192 | * | fl.log("PositionFees account USER11 hit");
193 | | }
194 | * | if (account == USER12) {
195 | * | fl.log("PositionFees account USER12 hit");
196 | | }
197 | * | if (account == USER13) {
198 | * | fl.log("PositionFees account USER13 hit");
199 | | }
200 | | }
201 | * | function _logPositionMarketCoverage(address market) internal {
202 | * | if (market == address(market_0_WETH_USDC)) {
203 | | fl.log("Position market market_0_WETH_USDC hit");
204 | | }
205 | |
206 | * | if (market == address(market_WBTC_WBTC_USDC)) {
207 | * | fl.log("Position market market_WBTC_WBTC_USDC hit");
208 | | }
209 | * | if (market == address(market_WETH_WETH_USDC)) {
210 | * | fl.log("Position market market_WETH_WETH_USDC hit");
211 | | }
212 | * | if (market == address(market_WETH_WETH_USDT)) {
213 | * | fl.log("Position market market_WETH_WETH_USDT hit");
214 | | }
215 | | }
216 | |
217 | * | function _logPositionCollateralTokenCoverage(
218 | | address collateralToken
219 | | ) internal {
220 | * | if (collateralToken == address(WETH)) {
221 | * | fl.log("Position collateralToken is WETH");
222 | | }
223 | * | if (collateralToken == address(WBTC)) {
224 | * | fl.log("Position collateralToken is WBTC");
225 | | }
226 | * | if (collateralToken == address(USDC)) {
227 | * | fl.log("Position collateralToken is USDC");
228 | | }
229 | * | if (collateralToken == address(USDT)) {
230 | * | fl.log("Position collateralToken is USDT");
231 | | }
232 | * | if (collateralToken == address(SOL)) {
233 | | fl.log("Position collateralToken is SOL");
234 | | }
235 | | }
236 | |
237 | * | function _logPositionSizeInUsdCoverage(uint256 sizeInUsd) internal {
238 | * | if (sizeInUsd == 0) {
239 | | fl.log("Position sizeInUsd is 0");
240 | | }
241 | * | if (sizeInUsd > 0 && sizeInUsd <= 1e6) {
242 | | fl.log("Position sizeInUsd is between 0 and 1e6");
243 | | }
244 | * | if (sizeInUsd > 1e6 && sizeInUsd <= 1e12) {
245 | | fl.log("Position sizeInUsd is between 1e6 and 1e12");
246 | | }
247 | * | if (sizeInUsd > 1e12 && sizeInUsd <= 1e18) {
248 | | fl.log("Position sizeInUsd is between 1e12 and 1e18");
249 | | }
250 | * | if (sizeInUsd > 1e18 && sizeInUsd <= 1e24) {
251 | | fl.log("Position sizeInUsd is between 1e18 and 1e24");
252 | | }
253 | * | if (sizeInUsd > 1e24) {
254 | * | fl.log("Position sizeInUsd is greater than 1e24");
255 | | }
256 | | }
257 | |
258 | * | function _logPositionSizeInTokensCoverage(uint256 sizeInTokens) internal {
259 | * | if (sizeInTokens == 0) {
260 | | fl.log("Position sizeInTokens is 0");
261 | | }
262 | * | if (sizeInTokens > 0 && sizeInTokens <= 1e6) {
263 | * | fl.log("Position sizeInTokens is between 0 and 1e6");
264 | | }
265 | * | if (sizeInTokens > 1e6 && sizeInTokens <= 1e12) {
266 | * | fl.log("Position sizeInTokens is between 1e6 and 1e12");
267 | | }
268 | * | if (sizeInTokens > 1e12 && sizeInTokens <= 1e18) {
269 | * | fl.log("Position sizeInTokens is between 1e12 and 1e18");
270 | | }
271 | * | if (sizeInTokens > 1e18 && sizeInTokens <= 1e24) {
272 | * | fl.log("Position sizeInTokens is between 1e18 and 1e24");
273 | | }
274 | * | if (sizeInTokens > 1e24) {
275 | | fl.log("Position sizeInTokens is greater than 1e24");
276 | | }
277 | | }
278 | |
279 | * | function _logPositionCollateralAmountCoverage(
280 | | uint256 collateralAmount
281 | | ) internal {
282 | * | if (collateralAmount == 0) {
283 | | fl.log("Position collateralAmount is 0");
284 | | }
285 | * | if (collateralAmount > 0 && collateralAmount <= 1e6) {
286 | * | fl.log("Position collateralAmount is between 0 and 1e6");
287 | | }
288 | * | if (collateralAmount > 1e6 && collateralAmount <= 1e12) {
289 | * | fl.log("Position collateralAmount is between 1e6 and 1e12");
290 | | }
291 | * | if (collateralAmount > 1e12 && collateralAmount <= 1e18) {
292 | * | fl.log("Position collateralAmount is between 1e12 and 1e18");
293 | | }
294 | * | if (collateralAmount > 1e18 && collateralAmount <= 1e24) {
295 | * | fl.log("Position collateralAmount is between 1e18 and 1e24");
296 | | }
297 | * | if (collateralAmount > 1e24) {
298 | | fl.log("Position collateralAmount is greater than 1e24");
299 | | }
300 | | }
301 | |
302 | * | function _logPositionBorrowingFactorCoverage(
303 | | uint256 borrowingFactor
304 | | ) internal {
305 | * | if (borrowingFactor == 0) {
306 | * | fl.log("Position borrowingFactor is 0");
307 | | }
308 | * | if (borrowingFactor > 0 && borrowingFactor <= 1e6) {
309 | | fl.log("Position borrowingFactor is between 0 and 1e6");
310 | | }
311 | * | if (borrowingFactor > 1e6 && borrowingFactor <= 1e12) {
312 | | fl.log("Position borrowingFactor is between 1e6 and 1e12");
313 | | }
314 | * | if (borrowingFactor > 1e12 && borrowingFactor <= 1e18) {
315 | | fl.log("Position borrowingFactor is between 1e12 and 1e18");
316 | | }
317 | * | if (borrowingFactor > 1e18 && borrowingFactor <= 1e24) {
318 | | fl.log("Position borrowingFactor is between 1e18 and 1e24");
319 | | }
320 | * | if (borrowingFactor > 1e24) {
321 | | fl.log("Position borrowingFactor is greater than 1e24");
322 | | }
323 | | }
324 | |
325 | * | function _logPositionFundingFeeAmountPerSizeCoverage(
326 | | uint256 fundingFeeAmountPerSize
327 | | ) internal {
328 | * | if (fundingFeeAmountPerSize == 0) {
329 | * | fl.log("Position fundingFeeAmountPerSize is 0");
330 | | }
331 | * | if (fundingFeeAmountPerSize > 0 && fundingFeeAmountPerSize <= 1e6) {
332 | | fl.log("Position fundingFeeAmountPerSize is between 0 and 1e6");
333 | | }
334 | * | if (fundingFeeAmountPerSize > 1e6 && fundingFeeAmountPerSize <= 1e12) {
335 | | fl.log("Position fundingFeeAmountPerSize is between 1e6 and 1e12");
336 | | }
337 | * | if (fundingFeeAmountPerSize > 1e12 && fundingFeeAmountPerSize <= 1e18) {
338 | * | fl.log("Position fundingFeeAmountPerSize is between 1e12 and 1e18");
339 | | }
340 | * | if (fundingFeeAmountPerSize > 1e18 && fundingFeeAmountPerSize <= 1e24) {
341 | * | fl.log("Position fundingFeeAmountPerSize is between 1e18 and 1e24");
342 | | }
343 | * | if (fundingFeeAmountPerSize > 1e24) {
344 | * | fl.log("Position fundingFeeAmountPerSize is greater than 1e24");
345 | | }
346 | | }
347 | |
348 | * | function _logPositionLongTokenClaimableFundingAmountPerSizeCoverage(
349 | | uint256 longTokenClaimableFundingAmountPerSize
350 | | ) internal {
351 | * | if (longTokenClaimableFundingAmountPerSize == 0) {
352 | * | fl.log("Position longTokenClaimableFundingAmountPerSize is 0");
353 | | }
354 | * | if (
355 | * | longTokenClaimableFundingAmountPerSize > 0 &&
356 | * | longTokenClaimableFundingAmountPerSize <= 1e6
357 | | ) {
358 | | fl.log(
359 | | "Position longTokenClaimableFundingAmountPerSize is between 0 and 1e6"
360 | | );
361 | | }
362 | * | if (
363 | * | longTokenClaimableFundingAmountPerSize > 1e6 &&
364 | * | longTokenClaimableFundingAmountPerSize <= 1e12
365 | | ) {
366 | | fl.log(
367 | | "Position longTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
368 | | );
369 | | }
370 | * | if (
371 | * | longTokenClaimableFundingAmountPerSize > 1e12 &&
372 | * | longTokenClaimableFundingAmountPerSize <= 1e18
373 | | ) {
374 | * | fl.log(
375 | | "Position longTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
376 | | );
377 | | }
378 | * | if (
379 | * | longTokenClaimableFundingAmountPerSize > 1e18 &&
380 | * | longTokenClaimableFundingAmountPerSize <= 1e24
381 | | ) {
382 | * | fl.log(
383 | | "Position longTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
384 | | );
385 | | }
386 | * | if (longTokenClaimableFundingAmountPerSize > 1e24) {
387 | * | fl.log(
388 | | "Position longTokenClaimableFundingAmountPerSize is greater than 1e24"
389 | | );
390 | | }
391 | | }
392 | |
393 | * | function _logPositionShortTokenClaimableFundingAmountPerSizeCoverage(
394 | | uint256 shortTokenClaimableFundingAmountPerSize
395 | | ) internal {
396 | * | if (shortTokenClaimableFundingAmountPerSize == 0) {
397 | * | fl.log("Position shortTokenClaimableFundingAmountPerSize is 0");
398 | | }
399 | * | if (
400 | * | shortTokenClaimableFundingAmountPerSize > 0 &&
401 | * | shortTokenClaimableFundingAmountPerSize <= 1e6
402 | | ) {
403 | | fl.log(
404 | | "Position shortTokenClaimableFundingAmountPerSize is between 0 and 1e6"
405 | | );
406 | | }
407 | * | if (
408 | * | shortTokenClaimableFundingAmountPerSize > 1e6 &&
409 | * | shortTokenClaimableFundingAmountPerSize <= 1e12
410 | | ) {
411 | | fl.log(
412 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
413 | | );
414 | | }
415 | * | if (
416 | * | shortTokenClaimableFundingAmountPerSize > 1e12 &&
417 | * | shortTokenClaimableFundingAmountPerSize <= 1e18
418 | | ) {
419 | * | fl.log(
420 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
421 | | );
422 | | }
423 | * | if (
424 | * | shortTokenClaimableFundingAmountPerSize > 1e18 &&
425 | * | shortTokenClaimableFundingAmountPerSize <= 1e24
426 | | ) {
427 | * | fl.log(
428 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
429 | | );
430 | | }
431 | * | if (shortTokenClaimableFundingAmountPerSize > 1e24) {
432 | * | fl.log(
433 | | "Position shortTokenClaimableFundingAmountPerSize is greater than 1e24"
434 | | );
435 | | }
436 | | }
437 | |
438 | * | function _logPositionIncreasedAtBlockCoverage(
439 | | uint256 increasedAtBlock
440 | | ) internal {
441 | * | if (increasedAtBlock == 0) {
442 | | fl.log("Position increasedAtBlock is 0");
443 | | } else {
444 | * | fl.log("Position increasedAtBlock is non-zero");
445 | | }
446 | | }
447 | |
448 | * | function _logPositionDecreasedAtBlockCoverage(
449 | | uint256 decreasedAtBlock
450 | | ) internal {
451 | * | if (decreasedAtBlock == 0) {
452 | * | fl.log("Position decreasedAtBlock is 0");
453 | | } else {
454 | * | fl.log("Position decreasedAtBlock is non-zero");
455 | | }
456 | | }
457 | |
458 | * | function _logPositionIncreasedAtTimeCoverage(
459 | | uint256 increasedAtTime
460 | | ) internal {
461 | * | if (increasedAtTime == 0) {
462 | | fl.log("Position increasedAtTime is 0");
463 | | } else {
464 | * | fl.log("Position increasedAtTime is non-zero");
465 | | }
466 | | }
467 | |
468 | * | function _logPositionDecreasedAtTimeCoverage(
469 | | uint256 decreasedAtTime
470 | | ) internal {
471 | * | if (decreasedAtTime == 0) {
472 | * | fl.log("Position decreasedAtTime is 0");
473 | | } else {
474 | * | fl.log("Position decreasedAtTime is non-zero");
475 | | }
476 | | }
477 | |
478 | * | function _logPositionIsLongCoverage(bool isLong) internal {
479 | * | if (isLong) {
480 | * | fl.log("Position isLong is true");
481 | | } else {
482 | * | fl.log("Position isLong is false");
483 | | }
484 | | }
485 | |
486 | * | function _logPositionFeesReferralCodeCoverage(
487 | | bytes32 referralCode
488 | | ) internal {
489 | * | if (referralCode == bytes32(0)) {
490 | * | fl.log("PositionFees referralCode is empty");
491 | | } else {
492 | | fl.log("PositionFees referralCode is non-empty");
493 | | }
494 | | }
495 | |
496 | * | function _logPositionFeesAffiliateCoverage(address affiliate) internal {
497 | * | if (affiliate == address(0)) {
498 | * | fl.log("PositionFees affiliate is address(0)");
499 | | } else {
500 | | fl.log("PositionFees affiliate is non-zero address");
501 | | }
502 | | }
503 | |
504 | * | function _logPositionFeesTraderCoverage(address trader) internal {
505 | * | if (trader == USER0) {
506 | * | fl.log("PositionFees trader USER0 hit");
507 | | }
508 | * | if (trader == USER1) {
509 | * | fl.log("PositionFees trader USER1 hit");
510 | | }
511 | * | if (trader == USER2) {
512 | * | fl.log("PositionFees trader USER2 hit");
513 | | }
514 | * | if (trader == USER3) {
515 | * | fl.log("PositionFees trader USER3 hit");
516 | | }
517 | * | if (trader == USER4) {
518 | * | fl.log("PositionFees trader USER4 hit");
519 | | }
520 | * | if (trader == USER5) {
521 | * | fl.log("PositionFees trader USER5 hit");
522 | | }
523 | * | if (trader == USER6) {
524 | * | fl.log("PositionFees trader USER6 hit");
525 | | }
526 | * | if (trader == USER7) {
527 | * | fl.log("PositionFees trader USER7 hit");
528 | | }
529 | * | if (trader == USER8) {
530 | * | fl.log("PositionFees trader USER8 hit");
531 | | }
532 | * | if (trader == USER9) {
533 | * | fl.log("PositionFees trader USER9 hit");
534 | | }
535 | * | if (trader == USER10) {
536 | * | fl.log("PositionFees trader USER10 hit");
537 | | }
538 | * | if (trader == USER11) {
539 | * | fl.log("PositionFees trader USER11 hit");
540 | | }
541 | * | if (trader == USER12) {
542 | * | fl.log("PositionFees trader USER12 hit");
543 | | }
544 | * | if (trader == USER13) {
545 | * | fl.log("PositionFees trader USER13 hit");
546 | | }
547 | | }
548 | |
549 | * | function _logPositionFeesTotalRebateFactorCoverage(
550 | | uint256 totalRebateFactor
551 | | ) internal {
552 | * | if (totalRebateFactor == 0) {
553 | * | fl.log("PositionFees totalRebateFactor is 0");
554 | | }
555 | * | if (totalRebateFactor > 0 && totalRebateFactor <= 1e6) {
556 | | fl.log("PositionFees totalRebateFactor is between 0 and 1e6");
557 | | }
558 | * | if (totalRebateFactor > 1e6 && totalRebateFactor <= 1e12) {
559 | | fl.log("PositionFees totalRebateFactor is between 1e6 and 1e12");
560 | | }
561 | * | if (totalRebateFactor > 1e12 && totalRebateFactor <= 1e18) {
562 | | fl.log("PositionFees totalRebateFactor is between 1e12 and 1e18");
563 | | }
564 | * | if (totalRebateFactor > 1e18 && totalRebateFactor <= 1e24) {
565 | | fl.log("PositionFees totalRebateFactor is between 1e18 and 1e24");
566 | | }
567 | * | if (totalRebateFactor > 1e24) {
568 | | fl.log("PositionFees totalRebateFactor is greater than 1e24");
569 | | }
570 | | }
571 | |
572 | * | function _logPositionFeesTraderDiscountFactorCoverage(
573 | | uint256 traderDiscountFactor
574 | | ) internal {
575 | * | if (traderDiscountFactor == 0) {
576 | * | fl.log("PositionFees traderDiscountFactor is 0");
577 | | }
578 | * | if (traderDiscountFactor > 0 && traderDiscountFactor <= 1e6) {
579 | | fl.log("PositionFees traderDiscountFactor is between 0 and 1e6");
580 | | }
581 | * | if (traderDiscountFactor > 1e6 && traderDiscountFactor <= 1e12) {
582 | | fl.log("PositionFees traderDiscountFactor is between 1e6 and 1e12");
583 | | }
584 | * | if (traderDiscountFactor > 1e12 && traderDiscountFactor <= 1e18) {
585 | | fl.log(
586 | | "PositionFees traderDiscountFactor is between 1e12 and 1e18"
587 | | );
588 | | }
589 | * | if (traderDiscountFactor > 1e18 && traderDiscountFactor <= 1e24) {
590 | | fl.log(
591 | | "PositionFees traderDiscountFactor is between 1e18 and 1e24"
592 | | );
593 | | }
594 | * | if (traderDiscountFactor > 1e24) {
595 | | fl.log("PositionFees traderDiscountFactor is greater than 1e24");
596 | | }
597 | | }
598 | |
599 | * | function _logPositionFeesTotalRebateAmountCoverage(
600 | | uint256 totalRebateAmount
601 | | ) internal {
602 | * | if (totalRebateAmount == 0) {
603 | * | fl.log("PositionFees totalRebateAmount is 0");
604 | | }
605 | * | if (totalRebateAmount > 0 && totalRebateAmount <= 1e6) {
606 | | fl.log("PositionFees totalRebateAmount is between 0 and 1e6");
607 | | }
608 | * | if (totalRebateAmount > 1e6 && totalRebateAmount <= 1e12) {
609 | | fl.log("PositionFees totalRebateAmount is between 1e6 and 1e12");
610 | | }
611 | * | if (totalRebateAmount > 1e12 && totalRebateAmount <= 1e18) {
612 | | fl.log("PositionFees totalRebateAmount is between 1e12 and 1e18");
613 | | }
614 | * | if (totalRebateAmount > 1e18 && totalRebateAmount <= 1e24) {
615 | | fl.log("PositionFees totalRebateAmount is between 1e18 and 1e24");
616 | | }
617 | * | if (totalRebateAmount > 1e24) {
618 | | fl.log("PositionFees totalRebateAmount is greater than 1e24");
619 | | }
620 | | }
621 | |
622 | * | function _logPositionFeesTraderDiscountAmountCoverage(
623 | | uint256 traderDiscountAmount
624 | | ) internal {
625 | * | if (traderDiscountAmount == 0) {
626 | * | fl.log("PositionFees traderDiscountAmount is 0");
627 | | }
628 | * | if (traderDiscountAmount > 0 && traderDiscountAmount <= 1e6) {
629 | | fl.log("PositionFees traderDiscountAmount is between 0 and 1e6");
630 | | }
631 | * | if (traderDiscountAmount > 1e6 && traderDiscountAmount <= 1e12) {
632 | | fl.log("PositionFees traderDiscountAmount is between 1e6 and 1e12");
633 | | }
634 | * | if (traderDiscountAmount > 1e12 && traderDiscountAmount <= 1e18) {
635 | | fl.log(
636 | | "PositionFees traderDiscountAmount is between 1e12 and 1e18"
637 | | );
638 | | }
639 | * | if (traderDiscountAmount > 1e18 && traderDiscountAmount <= 1e24) {
640 | | fl.log(
641 | | "PositionFees traderDiscountAmount is between 1e18 and 1e24"
642 | | );
643 | | }
644 | * | if (traderDiscountAmount > 1e24) {
645 | | fl.log("PositionFees traderDiscountAmount is greater than 1e24");
646 | | }
647 | | }
648 | |
649 | * | function _logPositionFeesAffiliateRewardAmountCoverage(
650 | | uint256 affiliateRewardAmount
651 | | ) internal {
652 | * | if (affiliateRewardAmount == 0) {
653 | * | fl.log("PositionFees affiliateRewardAmount is 0");
654 | | }
655 | * | if (affiliateRewardAmount > 0 && affiliateRewardAmount <= 1e6) {
656 | | fl.log("PositionFees affiliateRewardAmount is between 0 and 1e6");
657 | | }
658 | * | if (affiliateRewardAmount > 1e6 && affiliateRewardAmount <= 1e12) {
659 | | fl.log(
660 | | "PositionFees affiliateRewardAmount is between 1e6 and 1e12"
661 | | );
662 | | }
663 | * | if (affiliateRewardAmount > 1e12 && affiliateRewardAmount <= 1e18) {
664 | | fl.log(
665 | | "PositionFees affiliateRewardAmount is between 1e12 and 1e18"
666 | | );
667 | | }
668 | * | if (affiliateRewardAmount > 1e18 && affiliateRewardAmount <= 1e24) {
669 | | fl.log(
670 | | "PositionFees affiliateRewardAmount is between 1e18 and 1e24"
671 | | );
672 | | }
673 | * | if (affiliateRewardAmount > 1e24) {
674 | | fl.log("PositionFees affiliateRewardAmount is greater than 1e24");
675 | | }
676 | | }
677 | |
678 | * | function _logPositionFeesFundingFeeAmountCoverage(
679 | | uint256 fundingFeeAmount
680 | | ) internal {
681 | * | if (fundingFeeAmount == 0) {
682 | * | fl.log("PositionFees fundingFeeAmount is 0");
683 | | }
684 | * | if (fundingFeeAmount > 0 && fundingFeeAmount <= 1e6) {
685 | * | fl.log("PositionFees fundingFeeAmount is between 0 and 1e6");
686 | | }
687 | * | if (fundingFeeAmount > 1e6 && fundingFeeAmount <= 1e12) {
688 | * | fl.log("PositionFees fundingFeeAmount is between 1e6 and 1e12");
689 | | }
690 | * | if (fundingFeeAmount > 1e12 && fundingFeeAmount <= 1e18) {
691 | * | fl.log("PositionFees fundingFeeAmount is between 1e12 and 1e18");
692 | | }
693 | * | if (fundingFeeAmount > 1e18 && fundingFeeAmount <= 1e24) {
694 | * | fl.log("PositionFees fundingFeeAmount is between 1e18 and 1e24");
695 | | }
696 | * | if (fundingFeeAmount > 1e24) {
697 | | fl.log("PositionFees fundingFeeAmount is greater than 1e24");
698 | | }
699 | | }
700 | |
701 | * | function _logPositionFeesClaimableLongTokenAmountCoverage(
702 | | uint256 claimableLongTokenAmount
703 | | ) internal {
704 | * | if (claimableLongTokenAmount == 0) {
705 | * | fl.log("PositionFees claimableLongTokenAmount is 0");
706 | | }
707 | * | if (claimableLongTokenAmount > 0 && claimableLongTokenAmount <= 1e6) {
708 | | fl.log(
709 | | "PositionFees claimableLongTokenAmount is between 0 and 1e6"
710 | | );
711 | | }
712 | * | if (
713 | * | claimableLongTokenAmount > 1e6 && claimableLongTokenAmount <= 1e12
714 | | ) {
715 | | fl.log(
716 | | "PositionFees claimableLongTokenAmount is between 1e6 and 1e12"
717 | | );
718 | | }
719 | * | if (
720 | * | claimableLongTokenAmount > 1e12 && claimableLongTokenAmount <= 1e18
721 | | ) {
722 | | fl.log(
723 | | "PositionFees claimableLongTokenAmount is between 1e12 and 1e18"
724 | | );
725 | | }
726 | * | if (
727 | * | claimableLongTokenAmount > 1e18 && claimableLongTokenAmount <= 1e24
728 | | ) {
729 | | fl.log(
730 | | "PositionFees claimableLongTokenAmount is between 1e18 and 1e24"
731 | | );
732 | | }
733 | * | if (claimableLongTokenAmount > 1e24) {
734 | | fl.log(
735 | | "PositionFees claimableLongTokenAmount is greater than 1e24"
736 | | );
737 | | }
738 | | }
739 | |
740 | * | function _logPositionFeesClaimableShortTokenAmountCoverage(
741 | | uint256 claimableShortTokenAmount
742 | | ) internal {
743 | * | if (claimableShortTokenAmount == 0) {
744 | * | fl.log("PositionFees claimableShortTokenAmount is 0");
745 | | }
746 | * | if (claimableShortTokenAmount > 0 && claimableShortTokenAmount <= 1e6) {
747 | | fl.log(
748 | | "PositionFees claimableShortTokenAmount is between 0 and 1e6"
749 | | );
750 | | }
751 | * | if (
752 | * | claimableShortTokenAmount > 1e6 && claimableShortTokenAmount <= 1e12
753 | | ) {
754 | * | fl.log(
755 | | "PositionFees claimableShortTokenAmount is between 1e6 and 1e12"
756 | | );
757 | | }
758 | * | if (
759 | * | claimableShortTokenAmount > 1e12 &&
760 | * | claimableShortTokenAmount <= 1e18
761 | | ) {
762 | * | fl.log(
763 | | "PositionFees claimableShortTokenAmount is between 1e12 and 1e18"
764 | | );
765 | | }
766 | * | if (
767 | * | claimableShortTokenAmount > 1e18 &&
768 | | claimableShortTokenAmount <= 1e24
769 | | ) {
770 | | fl.log(
771 | | "PositionFees claimableShortTokenAmount is between 1e18 and 1e24"
772 | | );
773 | | }
774 | * | if (claimableShortTokenAmount > 1e24) {
775 | | fl.log(
776 | | "PositionFees claimableShortTokenAmount is greater than 1e24"
777 | | );
778 | | }
779 | | }
780 | |
781 | * | function _logPositionFeesLatestFundingFeeAmountPerSizeCoverage(
782 | | uint256 latestFundingFeeAmountPerSize
783 | | ) internal {
784 | * | if (latestFundingFeeAmountPerSize == 0) {
785 | * | fl.log("PositionFees latestFundingFeeAmountPerSize is 0");
786 | | }
787 | * | if (
788 | * | latestFundingFeeAmountPerSize > 0 &&
789 | * | latestFundingFeeAmountPerSize <= 1e6
790 | | ) {
791 | | fl.log(
792 | | "PositionFees latestFundingFeeAmountPerSize is between 0 and 1e6"
793 | | );
794 | | }
795 | * | if (
796 | * | latestFundingFeeAmountPerSize > 1e6 &&
797 | * | latestFundingFeeAmountPerSize <= 1e12
798 | | ) {
799 | | fl.log(
800 | | "PositionFees latestFundingFeeAmountPerSize is between 1e6 and 1e12"
801 | | );
802 | | }
803 | * | if (
804 | * | latestFundingFeeAmountPerSize > 1e12 &&
805 | * | latestFundingFeeAmountPerSize <= 1e18
806 | | ) {
807 | * | fl.log(
808 | | "PositionFees latestFundingFeeAmountPerSize is between 1e12 and 1e18"
809 | | );
810 | | }
811 | * | if (
812 | * | latestFundingFeeAmountPerSize > 1e18 &&
813 | * | latestFundingFeeAmountPerSize <= 1e24
814 | | ) {
815 | * | fl.log(
816 | | "PositionFees latestFundingFeeAmountPerSize is between 1e18 and 1e24"
817 | | );
818 | | }
819 | * | if (latestFundingFeeAmountPerSize > 1e24) {
820 | * | fl.log(
821 | | "PositionFees latestFundingFeeAmountPerSize is greater than 1e24"
822 | | );
823 | | }
824 | | }
825 | |
826 | * | function _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage(
827 | | uint256 latestLongTokenClaimableFundingAmountPerSize
828 | | ) internal {
829 | * | if (latestLongTokenClaimableFundingAmountPerSize == 0) {
830 | * | fl.log(
831 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is 0"
832 | | );
833 | | }
834 | * | if (
835 | * | latestLongTokenClaimableFundingAmountPerSize > 0 &&
836 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e6
837 | | ) {
838 | | fl.log(
839 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 0 and 1e6"
840 | | );
841 | | }
842 | * | if (
843 | * | latestLongTokenClaimableFundingAmountPerSize > 1e6 &&
844 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e12
845 | | ) {
846 | | fl.log(
847 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
848 | | );
849 | | }
850 | * | if (
851 | * | latestLongTokenClaimableFundingAmountPerSize > 1e12 &&
852 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e18
853 | | ) {
854 | * | fl.log(
855 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
856 | | );
857 | | }
858 | * | if (
859 | * | latestLongTokenClaimableFundingAmountPerSize > 1e18 &&
860 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e24
861 | | ) {
862 | * | fl.log(
863 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
864 | | );
865 | | }
866 | * | if (latestLongTokenClaimableFundingAmountPerSize > 1e24) {
867 | * | fl.log(
868 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is greater than 1e24"
869 | | );
870 | | }
871 | | }
872 | |
873 | * | function _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage(
874 | | uint256 latestShortTokenClaimableFundingAmountPerSize
875 | | ) internal {
876 | * | if (latestShortTokenClaimableFundingAmountPerSize == 0) {
877 | * | fl.log(
878 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is 0"
879 | | );
880 | | }
881 | * | if (
882 | * | latestShortTokenClaimableFundingAmountPerSize > 0 &&
883 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e6
884 | | ) {
885 | | fl.log(
886 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 0 and 1e6"
887 | | );
888 | | }
889 | * | if (
890 | * | latestShortTokenClaimableFundingAmountPerSize > 1e6 &&
891 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e12
892 | | ) {
893 | | fl.log(
894 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12"
895 | | );
896 | | }
897 | * | if (
898 | * | latestShortTokenClaimableFundingAmountPerSize > 1e12 &&
899 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e18
900 | | ) {
901 | * | fl.log(
902 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18"
903 | | );
904 | | }
905 | * | if (
906 | * | latestShortTokenClaimableFundingAmountPerSize > 1e18 &&
907 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e24
908 | | ) {
909 | * | fl.log(
910 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24"
911 | | );
912 | | }
913 | * | if (latestShortTokenClaimableFundingAmountPerSize > 1e24) {
914 | * | fl.log(
915 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is greater than 1e24"
916 | | );
917 | | }
918 | | }
919 | |
920 | * | function _logPositionFeesBorrowingFeeUsdCoverage(
921 | | uint256 borrowingFeeUsd
922 | | ) internal {
923 | * | if (borrowingFeeUsd == 0) {
924 | * | fl.log("PositionFees borrowingFeeUsd is 0");
925 | | }
926 | * | if (borrowingFeeUsd > 0 && borrowingFeeUsd <= 1e6) {
927 | | fl.log("PositionFees borrowingFeeUsd is between 0 and 1e6");
928 | | }
929 | * | if (borrowingFeeUsd > 1e6 && borrowingFeeUsd <= 1e12) {
930 | | fl.log("PositionFees borrowingFeeUsd is between 1e6 and 1e12");
931 | | }
932 | * | if (borrowingFeeUsd > 1e12 && borrowingFeeUsd <= 1e18) {
933 | | fl.log("PositionFees borrowingFeeUsd is between 1e12 and 1e18");
934 | | }
935 | * | if (borrowingFeeUsd > 1e18 && borrowingFeeUsd <= 1e24) {
936 | | fl.log("PositionFees borrowingFeeUsd is between 1e18 and 1e24");
937 | | }
938 | * | if (borrowingFeeUsd > 1e24) {
939 | | fl.log("PositionFees borrowingFeeUsd is greater than 1e24");
940 | | }
941 | | }
942 | |
943 | * | function _logPositionFeesBorrowingFeeAmountCoverage(
944 | | uint256 borrowingFeeAmount
945 | | ) internal {
946 | * | if (borrowingFeeAmount == 0) {
947 | * | fl.log("PositionFees borrowingFeeAmount is 0");
948 | | }
949 | * | if (borrowingFeeAmount > 0 && borrowingFeeAmount <= 1e6) {
950 | | fl.log("PositionFees borrowingFeeAmount is between 0 and 1e6");
951 | | }
952 | * | if (borrowingFeeAmount > 1e6 && borrowingFeeAmount <= 1e12) {
953 | | fl.log("PositionFees borrowingFeeAmount is between 1e6 and 1e12");
954 | | }
955 | * | if (borrowingFeeAmount > 1e12 && borrowingFeeAmount <= 1e18) {
956 | | fl.log("PositionFees borrowingFeeAmount is between 1e12 and 1e18");
957 | | }
958 | * | if (borrowingFeeAmount > 1e18 && borrowingFeeAmount <= 1e24) {
959 | | fl.log("PositionFees borrowingFeeAmount is between 1e18 and 1e24");
960 | | }
961 | * | if (borrowingFeeAmount > 1e24) {
962 | | fl.log("PositionFees borrowingFeeAmount is greater than 1e24");
963 | | }
964 | | }
965 | |
966 | * | function _logPositionFeesBorrowingFeeReceiverFactorCoverage(
967 | | uint256 borrowingFeeReceiverFactor
968 | | ) internal {
969 | * | if (borrowingFeeReceiverFactor == 0) {
970 | * | fl.log("PositionFees borrowingFeeReceiverFactor is 0");
971 | | }
972 | * | if (
973 | * | borrowingFeeReceiverFactor > 0 && borrowingFeeReceiverFactor <= 1e6
974 | | ) {
975 | | fl.log(
976 | | "PositionFees borrowingFeeReceiverFactor is between 0 and 1e6"
977 | | );
978 | | }
979 | * | if (
980 | * | borrowingFeeReceiverFactor > 1e6 &&
981 | | borrowingFeeReceiverFactor <= 1e12
982 | | ) {
983 | | fl.log(
984 | | "PositionFees borrowingFeeReceiverFactor is between 1e6 and 1e12"
985 | | );
986 | | }
987 | * | if (
988 | * | borrowingFeeReceiverFactor > 1e12 &&
989 | | borrowingFeeReceiverFactor <= 1e18
990 | | ) {
991 | | fl.log(
992 | | "PositionFees borrowingFeeReceiverFactor is between 1e12 and 1e18"
993 | | );
994 | | }
995 | * | if (
996 | * | borrowingFeeReceiverFactor > 1e18 &&
997 | | borrowingFeeReceiverFactor <= 1e24
998 | | ) {
999 | | fl.log(
1000 | | "PositionFees borrowingFeeReceiverFactor is between 1e18 and 1e24"
1001 | | );
1002 | | }
1003 | * | if (borrowingFeeReceiverFactor > 1e24) {
1004 | | fl.log(
1005 | | "PositionFees borrowingFeeReceiverFactor is greater than 1e24"
1006 | | );
1007 | | }
1008 | | }
1009 | |
1010 | * | function _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage(
1011 | | uint256 borrowingFeeAmountForFeeReceiver
1012 | | ) internal {
1013 | * | if (borrowingFeeAmountForFeeReceiver == 0) {
1014 | * | fl.log("PositionFees borrowingFeeAmountForFeeReceiver is 0");
1015 | | }
1016 | * | if (
1017 | * | borrowingFeeAmountForFeeReceiver > 0 &&
1018 | | borrowingFeeAmountForFeeReceiver <= 1e6
1019 | | ) {
1020 | | fl.log(
1021 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 0 and 1e6"
1022 | | );
1023 | | }
1024 | * | if (
1025 | * | borrowingFeeAmountForFeeReceiver > 1e6 &&
1026 | | borrowingFeeAmountForFeeReceiver <= 1e12
1027 | | ) {
1028 | | fl.log(
1029 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e6 and 1e12"
1030 | | );
1031 | | }
1032 | * | if (
1033 | * | borrowingFeeAmountForFeeReceiver > 1e12 &&
1034 | | borrowingFeeAmountForFeeReceiver <= 1e18
1035 | | ) {
1036 | | fl.log(
1037 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e12 and 1e18"
1038 | | );
1039 | | }
1040 | * | if (
1041 | * | borrowingFeeAmountForFeeReceiver > 1e18 &&
1042 | | borrowingFeeAmountForFeeReceiver <= 1e24
1043 | | ) {
1044 | | fl.log(
1045 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e18 and 1e24"
1046 | | );
1047 | | }
1048 | * | if (borrowingFeeAmountForFeeReceiver > 1e24) {
1049 | | fl.log(
1050 | | "PositionFees borrowingFeeAmountForFeeReceiver is greater than 1e24"
1051 | | );
1052 | | }
1053 | | }
1054 | |
1055 | * | function _logPositionFeesUiFeeReceiverCoverage(
1056 | | address uiFeeReceiver
1057 | | ) internal {
1058 | * | if (uiFeeReceiver == address(0)) {
1059 | * | fl.log("PositionFees uiFeeReceiver is address(0)");
1060 | | } else {
1061 | | fl.log("PositionFees uiFeeReceiver is non-zero address");
1062 | | }
1063 | | }
1064 | |
1065 | * | function _logPositionFeesUiFeeReceiverFactorCoverage(
1066 | | uint256 uiFeeReceiverFactor
1067 | | ) internal {
1068 | * | if (uiFeeReceiverFactor == 0) {
1069 | * | fl.log("PositionFees uiFeeReceiverFactor is 0");
1070 | | }
1071 | * | if (uiFeeReceiverFactor > 0 && uiFeeReceiverFactor <= 1e6) {
1072 | | fl.log("PositionFees uiFeeReceiverFactor is between 0 and 1e6");
1073 | | }
1074 | * | if (uiFeeReceiverFactor > 1e6 && uiFeeReceiverFactor <= 1e12) {
1075 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e6 and 1e12");
1076 | | }
1077 | * | if (uiFeeReceiverFactor > 1e12 && uiFeeReceiverFactor <= 1e18) {
1078 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e12 and 1e18");
1079 | | }
1080 | * | if (uiFeeReceiverFactor > 1e18 && uiFeeReceiverFactor <= 1e24) {
1081 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e18 and 1e24");
1082 | | }
1083 | * | if (uiFeeReceiverFactor > 1e24) {
1084 | | fl.log("PositionFees uiFeeReceiverFactor is greater than 1e24");
1085 | | }
1086 | | }
1087 | |
1088 | * | function _logPositionFeesUiFeeAmountCoverage(uint256 uiFeeAmount) internal {
1089 | * | if (uiFeeAmount == 0) {
1090 | * | fl.log("PositionFees uiFeeAmount is 0");
1091 | | }
1092 | * | if (uiFeeAmount > 0 && uiFeeAmount <= 1e6) {
1093 | | fl.log("PositionFees uiFeeAmount is between 0 and 1e6");
1094 | | }
1095 | * | if (uiFeeAmount > 1e6 && uiFeeAmount <= 1e12) {
1096 | | fl.log("PositionFees uiFeeAmount is between 1e6 and 1e12");
1097 | | }
1098 | * | if (uiFeeAmount > 1e12 && uiFeeAmount <= 1e18) {
1099 | | fl.log("PositionFees uiFeeAmount is between 1e12 and 1e18");
1100 | | }
1101 | * | if (uiFeeAmount > 1e18 && uiFeeAmount <= 1e24) {
1102 | | fl.log("PositionFees uiFeeAmount is between 1e18 and 1e24");
1103 | | }
1104 | * | if (uiFeeAmount > 1e24) {
1105 | | fl.log("PositionFees uiFeeAmount is greater than 1e24");
1106 | | }
1107 | | }
1108 | |
1109 | * | function _logPositionFeesCollateralTokenPriceCoverage(
1110 | | uint256 collateralTokenPrice
1111 | | ) internal {
1112 | * | if (collateralTokenPrice == 0) {
1113 | | fl.log("PositionFees collateralTokenPrice is 0");
1114 | | }
1115 | * | if (collateralTokenPrice > 0 && collateralTokenPrice <= 1e6) {
1116 | | fl.log("PositionFees collateralTokenPrice is between 0 and 1e6");
1117 | | }
1118 | * | if (collateralTokenPrice > 1e6 && collateralTokenPrice <= 1e12) {
1119 | | fl.log("PositionFees collateralTokenPrice is between 1e6 and 1e12");
1120 | | }
1121 | * | if (collateralTokenPrice > 1e12 && collateralTokenPrice <= 1e18) {
1122 | * | fl.log(
1123 | | "PositionFees collateralTokenPrice is between 1e12 and 1e18"
1124 | | );
1125 | | }
1126 | * | if (collateralTokenPrice > 1e18 && collateralTokenPrice <= 1e24) {
1127 | * | fl.log(
1128 | | "PositionFees collateralTokenPrice is between 1e18 and 1e24"
1129 | | );
1130 | | }
1131 | * | if (collateralTokenPrice > 1e24) {
1132 | * | fl.log("PositionFees collateralTokenPrice is greater than 1e24");
1133 | | }
1134 | | }
1135 | |
1136 | * | function _logPositionFeesPositionFeeFactorCoverage(
1137 | | uint256 positionFeeFactor
1138 | | ) internal {
1139 | * | if (positionFeeFactor == 0) {
1140 | * | fl.log("PositionFees positionFeeFactor is 0");
1141 | | }
1142 | * | if (positionFeeFactor > 0 && positionFeeFactor <= 1e6) {
1143 | | fl.log("PositionFees positionFeeFactor is between 0 and 1e6");
1144 | | }
1145 | * | if (positionFeeFactor > 1e6 && positionFeeFactor <= 1e12) {
1146 | | fl.log("PositionFees positionFeeFactor is between 1e6 and 1e12");
1147 | | }
1148 | * | if (positionFeeFactor > 1e12 && positionFeeFactor <= 1e18) {
1149 | | fl.log("PositionFees positionFeeFactor is between 1e12 and 1e18");
1150 | | }
1151 | * | if (positionFeeFactor > 1e18 && positionFeeFactor <= 1e24) {
1152 | | fl.log("PositionFees positionFeeFactor is between 1e18 and 1e24");
1153 | | }
1154 | * | if (positionFeeFactor > 1e24) {
1155 | | fl.log("PositionFees positionFeeFactor is greater than 1e24");
1156 | | }
1157 | | }
1158 | |
1159 | * | function _logPositionFeesProtocolFeeAmountCoverage(
1160 | | uint256 protocolFeeAmount
1161 | | ) internal {
1162 | * | if (protocolFeeAmount == 0) {
1163 | * | fl.log("PositionFees protocolFeeAmount is 0");
1164 | | }
1165 | * | if (protocolFeeAmount > 0 && protocolFeeAmount <= 1e6) {
1166 | | fl.log("PositionFees protocolFeeAmount is between 0 and 1e6");
1167 | | }
1168 | * | if (protocolFeeAmount > 1e6 && protocolFeeAmount <= 1e12) {
1169 | | fl.log("PositionFees protocolFeeAmount is between 1e6 and 1e12");
1170 | | }
1171 | * | if (protocolFeeAmount > 1e12 && protocolFeeAmount <= 1e18) {
1172 | | fl.log("PositionFees protocolFeeAmount is between 1e12 and 1e18");
1173 | | }
1174 | * | if (protocolFeeAmount > 1e18 && protocolFeeAmount <= 1e24) {
1175 | | fl.log("PositionFees protocolFeeAmount is between 1e18 and 1e24");
1176 | | }
1177 | * | if (protocolFeeAmount > 1e24) {
1178 | | fl.log("PositionFees protocolFeeAmount is greater than 1e24");
1179 | | }
1180 | | }
1181 | |
1182 | * | function _logPositionFeesPositionFeeReceiverFactorCoverage(
1183 | | uint256 positionFeeReceiverFactor
1184 | | ) internal {
1185 | * | if (positionFeeReceiverFactor == 0) {
1186 | * | fl.log("PositionFees positionFeeReceiverFactor is 0");
1187 | | }
1188 | * | if (positionFeeReceiverFactor > 0 && positionFeeReceiverFactor <= 1e6) {
1189 | | fl.log(
1190 | | "PositionFees positionFeeReceiverFactor is between 0 and 1e6"
1191 | | );
1192 | | }
1193 | * | if (
1194 | * | positionFeeReceiverFactor > 1e6 && positionFeeReceiverFactor <= 1e12
1195 | | ) {
1196 | | fl.log(
1197 | | "PositionFees positionFeeReceiverFactor is between 1e6 and 1e12"
1198 | | );
1199 | | }
1200 | * | if (
1201 | * | positionFeeReceiverFactor > 1e12 &&
1202 | | positionFeeReceiverFactor <= 1e18
1203 | | ) {
1204 | | fl.log(
1205 | | "PositionFees positionFeeReceiverFactor is between 1e12 and 1e18"
1206 | | );
1207 | | }
1208 | * | if (
1209 | * | positionFeeReceiverFactor > 1e18 &&
1210 | | positionFeeReceiverFactor <= 1e24
1211 | | ) {
1212 | | fl.log(
1213 | | "PositionFees positionFeeReceiverFactor is between 1e18 and 1e24"
1214 | | );
1215 | | }
1216 | * | if (positionFeeReceiverFactor > 1e24) {
1217 | | fl.log(
1218 | | "PositionFees positionFeeReceiverFactor is greater than 1e24"
1219 | | );
1220 | | }
1221 | | }
1222 | |
1223 | * | function _logPositionFeesFeeReceiverAmountCoverage(
1224 | | uint256 feeReceiverAmount
1225 | | ) internal {
1226 | * | if (feeReceiverAmount == 0) {
1227 | * | fl.log("PositionFees feeReceiverAmount is 0");
1228 | | }
1229 | * | if (feeReceiverAmount > 0 && feeReceiverAmount <= 1e6) {
1230 | | fl.log("PositionFees feeReceiverAmount is between 0 and 1e6");
1231 | | }
1232 | * | if (feeReceiverAmount > 1e6 && feeReceiverAmount <= 1e12) {
1233 | | fl.log("PositionFees feeReceiverAmount is between 1e6 and 1e12");
1234 | | }
1235 | * | if (feeReceiverAmount > 1e12 && feeReceiverAmount <= 1e18) {
1236 | | fl.log("PositionFees feeReceiverAmount is between 1e12 and 1e18");
1237 | | }
1238 | * | if (feeReceiverAmount > 1e18 && feeReceiverAmount <= 1e24) {
1239 | | fl.log("PositionFees feeReceiverAmount is between 1e18 and 1e24");
1240 | | }
1241 | * | if (feeReceiverAmount > 1e24) {
1242 | | fl.log("PositionFees feeReceiverAmount is greater than 1e24");
1243 | | }
1244 | | }
1245 | |
1246 | * | function _logPositionFeesFeeAmountForPoolCoverage(
1247 | | uint256 feeAmountForPool
1248 | | ) internal {
1249 | * | if (feeAmountForPool == 0) {
1250 | * | fl.log("PositionFees feeAmountForPool is 0");
1251 | | }
1252 | * | if (feeAmountForPool > 0 && feeAmountForPool <= 1e6) {
1253 | | fl.log("PositionFees feeAmountForPool is between 0 and 1e6");
1254 | | }
1255 | * | if (feeAmountForPool > 1e6 && feeAmountForPool <= 1e12) {
1256 | | fl.log("PositionFees feeAmountForPool is between 1e6 and 1e12");
1257 | | }
1258 | * | if (feeAmountForPool > 1e12 && feeAmountForPool <= 1e18) {
1259 | | fl.log("PositionFees feeAmountForPool is between 1e12 and 1e18");
1260 | | }
1261 | * | if (feeAmountForPool > 1e18 && feeAmountForPool <= 1e24) {
1262 | | fl.log("PositionFees feeAmountForPool is between 1e18 and 1e24");
1263 | | }
1264 | * | if (feeAmountForPool > 1e24) {
1265 | | fl.log("PositionFees feeAmountForPool is greater than 1e24");
1266 | | }
1267 | | }
1268 | |
1269 | * | function _logPositionFeesPositionFeeAmountForPoolCoverage(
1270 | | uint256 positionFeeAmountForPool
1271 | | ) internal {
1272 | * | if (positionFeeAmountForPool == 0) {
1273 | * | fl.log("PositionFees positionFeeAmountForPool is 0");
1274 | | }
1275 | * | if (positionFeeAmountForPool > 0 && positionFeeAmountForPool <= 1e6) {
1276 | | fl.log(
1277 | | "PositionFees positionFeeAmountForPool is between 0 and 1e6"
1278 | | );
1279 | | }
1280 | * | if (
1281 | * | positionFeeAmountForPool > 1e6 && positionFeeAmountForPool <= 1e12
1282 | | ) {
1283 | | fl.log(
1284 | | "PositionFees positionFeeAmountForPool is between 1e6 and 1e12"
1285 | | );
1286 | | }
1287 | * | if (
1288 | * | positionFeeAmountForPool > 1e12 && positionFeeAmountForPool <= 1e18
1289 | | ) {
1290 | | fl.log(
1291 | | "PositionFees positionFeeAmountForPool is between 1e12 and 1e18"
1292 | | );
1293 | | }
1294 | * | if (
1295 | * | positionFeeAmountForPool > 1e18 && positionFeeAmountForPool <= 1e24
1296 | | ) {
1297 | | fl.log(
1298 | | "PositionFees positionFeeAmountForPool is between 1e18 and 1e24"
1299 | | );
1300 | | }
1301 | * | if (positionFeeAmountForPool > 1e24) {
1302 | | fl.log(
1303 | | "PositionFees positionFeeAmountForPool is greater than 1e24"
1304 | | );
1305 | | }
1306 | | }
1307 | |
1308 | * | function _logPositionFeesPositionFeeAmountCoverage(
1309 | | uint256 positionFeeAmount
1310 | | ) internal {
1311 | * | if (positionFeeAmount == 0) {
1312 | * | fl.log("PositionFees positionFeeAmount is 0");
1313 | | }
1314 | * | if (positionFeeAmount > 0 && positionFeeAmount <= 1e6) {
1315 | | fl.log("PositionFees positionFeeAmount is between 0 and 1e6");
1316 | | }
1317 | * | if (positionFeeAmount > 1e6 && positionFeeAmount <= 1e12) {
1318 | | fl.log("PositionFees positionFeeAmount is between 1e6 and 1e12");
1319 | | }
1320 | * | if (positionFeeAmount > 1e12 && positionFeeAmount <= 1e18) {
1321 | | fl.log("PositionFees positionFeeAmount is between 1e12 and 1e18");
1322 | | }
1323 | * | if (positionFeeAmount > 1e18 && positionFeeAmount <= 1e24) {
1324 | | fl.log("PositionFees positionFeeAmount is between 1e18 and 1e24");
1325 | | }
1326 | * | if (positionFeeAmount > 1e24) {
1327 | | fl.log("PositionFees positionFeeAmount is greater than 1e24");
1328 | | }
1329 | | }
1330 | |
1331 | * | function _logPositionFeesTotalCostAmountExcludingFundingCoverage(
1332 | | uint256 totalCostAmountExcludingFunding
1333 | | ) internal {
1334 | * | if (totalCostAmountExcludingFunding == 0) {
1335 | * | fl.log("PositionFees totalCostAmountExcludingFunding is 0");
1336 | | }
1337 | * | if (
1338 | * | totalCostAmountExcludingFunding > 0 &&
1339 | | totalCostAmountExcludingFunding <= 1e6
1340 | | ) {
1341 | | fl.log(
1342 | | "PositionFees totalCostAmountExcludingFunding is between 0 and 1e6"
1343 | | );
1344 | | }
1345 | * | if (
1346 | * | totalCostAmountExcludingFunding > 1e6 &&
1347 | | totalCostAmountExcludingFunding <= 1e12
1348 | | ) {
1349 | | fl.log(
1350 | | "PositionFees totalCostAmountExcludingFunding is between 1e6 and 1e12"
1351 | | );
1352 | | }
1353 | * | if (
1354 | * | totalCostAmountExcludingFunding > 1e12 &&
1355 | | totalCostAmountExcludingFunding <= 1e18
1356 | | ) {
1357 | | fl.log(
1358 | | "PositionFees totalCostAmountExcludingFunding is between 1e12 and 1e18"
1359 | | );
1360 | | }
1361 | * | if (
1362 | * | totalCostAmountExcludingFunding > 1e18 &&
1363 | | totalCostAmountExcludingFunding <= 1e24
1364 | | ) {
1365 | | fl.log(
1366 | | "PositionFees totalCostAmountExcludingFunding is between 1e18 and 1e24"
1367 | | );
1368 | | }
1369 | * | if (totalCostAmountExcludingFunding > 1e24) {
1370 | | fl.log(
1371 | | "PositionFees totalCostAmountExcludingFunding is greater than 1e24"
1372 | | );
1373 | | }
1374 | | }
1375 | |
1376 | * | function _logPositionFeesTotalCostAmountCoverage(
1377 | | uint256 totalCostAmount
1378 | | ) internal {
1379 | * | if (totalCostAmount == 0) {
1380 | * | fl.log("PositionFees totalCostAmount is 0");
1381 | | }
1382 | * | if (totalCostAmount > 0 && totalCostAmount <= 1e6) {
1383 | * | fl.log("PositionFees totalCostAmount is between 0 and 1e6");
1384 | | }
1385 | * | if (totalCostAmount > 1e6 && totalCostAmount <= 1e12) {
1386 | * | fl.log("PositionFees totalCostAmount is between 1e6 and 1e12");
1387 | | }
1388 | * | if (totalCostAmount > 1e12 && totalCostAmount <= 1e18) {
1389 | * | fl.log("PositionFees totalCostAmount is between 1e12 and 1e18");
1390 | | }
1391 | * | if (totalCostAmount > 1e18 && totalCostAmount <= 1e24) {
1392 | * | fl.log("PositionFees totalCostAmount is between 1e18 and 1e24");
1393 | | }
1394 | * | if (totalCostAmount > 1e24) {
1395 | | fl.log("PositionFees totalCostAmount is greater than 1e24");
1396 | | }
1397 | | }
1398 | |
1399 | * | function _logExecutionPriceResultPriceImpactUsdCoverage(
1400 | | int256 priceImpactUsd
1401 | | ) internal {
1402 | * | if (priceImpactUsd == 0) {
1403 | * | fl.log("ExecutionPriceResult priceImpactUsd is 0");
1404 | | }
1405 | * | if (priceImpactUsd > 0 && priceImpactUsd <= 1e6) {
1406 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and 1e6");
1407 | | }
1408 | * | if (priceImpactUsd > 1e6 && priceImpactUsd <= 1e12) {
1409 | | fl.log(
1410 | | "ExecutionPriceResult priceImpactUsd is between 1e6 and 1e12"
1411 | | );
1412 | | }
1413 | * | if (priceImpactUsd > 1e12 && priceImpactUsd <= 1e18) {
1414 | | fl.log(
1415 | | "ExecutionPriceResult priceImpactUsd is between 1e12 and 1e18"
1416 | | );
1417 | | }
1418 | * | if (priceImpactUsd > 1e18 && priceImpactUsd <= 1e24) {
1419 | | fl.log(
1420 | | "ExecutionPriceResult priceImpactUsd is between 1e18 and 1e24"
1421 | | );
1422 | | }
1423 | * | if (priceImpactUsd > 1e24) {
1424 | | fl.log("ExecutionPriceResult priceImpactUsd is greater than 1e24");
1425 | | }
1426 | * | if (priceImpactUsd < 0 && priceImpactUsd >= -1e6) {
1427 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and -1e6");
1428 | | }
1429 | * | if (priceImpactUsd < -1e6 && priceImpactUsd >= -1e12) {
1430 | | fl.log(
1431 | | "ExecutionPriceResult priceImpactUsd is between -1e6 and -1e12"
1432 | | );
1433 | | }
1434 | * | if (priceImpactUsd < -1e12 && priceImpactUsd >= -1e18) {
1435 | | fl.log(
1436 | | "ExecutionPriceResult priceImpactUsd is between -1e12 and -1e18"
1437 | | );
1438 | | }
1439 | * | if (priceImpactUsd < -1e18 && priceImpactUsd >= -1e24) {
1440 | | fl.log(
1441 | | "ExecutionPriceResult priceImpactUsd is between -1e18 and -1e24"
1442 | | );
1443 | | }
1444 | * | if (priceImpactUsd < -1e24) {
1445 | | fl.log("ExecutionPriceResult priceImpactUsd is less than -1e24");
1446 | | }
1447 | | }
1448 | * | function _logExecutionPriceResultPriceImpactDiffUsdCoverage(
1449 | | uint256 priceImpactDiffUsd
1450 | | ) internal {
1451 | * | if (priceImpactDiffUsd == 0) {
1452 | * | fl.log("ExecutionPriceResult priceImpactDiffUsd is 0");
1453 | | }
1454 | * | if (priceImpactDiffUsd > 0 && priceImpactDiffUsd <= 1e6) {
1455 | | fl.log(
1456 | | "ExecutionPriceResult priceImpactDiffUsd is between 0 and 1e6"
1457 | | );
1458 | | }
1459 | * | if (priceImpactDiffUsd > 1e6 && priceImpactDiffUsd <= 1e12) {
1460 | | fl.log(
1461 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e6 and 1e12"
1462 | | );
1463 | | }
1464 | * | if (priceImpactDiffUsd > 1e12 && priceImpactDiffUsd <= 1e18) {
1465 | | fl.log(
1466 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e12 and 1e18"
1467 | | );
1468 | | }
1469 | * | if (priceImpactDiffUsd > 1e18 && priceImpactDiffUsd <= 1e24) {
1470 | | fl.log(
1471 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e18 and 1e24"
1472 | | );
1473 | | }
1474 | * | if (priceImpactDiffUsd > 1e24) {
1475 | | fl.log(
1476 | | "ExecutionPriceResult priceImpactDiffUsd is greater than 1e24"
1477 | | );
1478 | | }
1479 | | }
1480 | * | function _logExecutionPriceResultExecutionPriceCoverage(
1481 | | uint256 executionPrice
1482 | | ) internal {
1483 | * | if (executionPrice == 0) {
1484 | | fl.log("ExecutionPriceResult executionPrice is 0");
1485 | | }
1486 | * | if (executionPrice > 0 && executionPrice <= 1e6) {
1487 | | fl.log("ExecutionPriceResult executionPrice is between 0 and 1e6");
1488 | | }
1489 | * | if (executionPrice > 1e6 && executionPrice <= 1e12) {
1490 | | fl.log(
1491 | | "ExecutionPriceResult executionPrice is between 1e6 and 1e12"
1492 | | );
1493 | | }
1494 | * | if (executionPrice > 1e12 && executionPrice <= 1e18) {
1495 | * | fl.log(
1496 | | "ExecutionPriceResult executionPrice is between 1e12 and 1e18"
1497 | | );
1498 | | }
1499 | * | if (executionPrice > 1e18 && executionPrice <= 1e24) {
1500 | | fl.log(
1501 | | "ExecutionPriceResult executionPrice is between 1e18 and 1e24"
1502 | | );
1503 | | }
1504 | * | if (executionPrice > 1e24) {
1505 | * | fl.log("ExecutionPriceResult executionPrice is greater than 1e24");
1506 | | }
1507 | | }
1508 | * | function _logPositionInfoBasePnlUsdCoverage(int256 basePnlUsd) internal {
1509 | * | if (basePnlUsd == 0) {
1510 | * | fl.log("PositionInfo basePnlUsd is 0");
1511 | | }
1512 | * | if (basePnlUsd > 0 && basePnlUsd <= 1e6) {
1513 | | fl.log("PositionInfo basePnlUsd is between 0 and 1e6");
1514 | | }
1515 | * | if (basePnlUsd > 1e6 && basePnlUsd <= 1e12) {
1516 | | fl.log("PositionInfo basePnlUsd is between 1e6 and 1e12");
1517 | | }
1518 | * | if (basePnlUsd > 1e12 && basePnlUsd <= 1e18) {
1519 | | fl.log("PositionInfo basePnlUsd is between 1e12 and 1e18");
1520 | | }
1521 | * | if (basePnlUsd > 1e18 && basePnlUsd <= 1e24) {
1522 | | fl.log("PositionInfo basePnlUsd is between 1e18 and 1e24");
1523 | | }
1524 | * | if (basePnlUsd > 1e24) {
1525 | * | fl.log("PositionInfo basePnlUsd is greater than 1e24");
1526 | | }
1527 | * | if (basePnlUsd < 0 && basePnlUsd >= -1e6) {
1528 | | fl.log("PositionInfo basePnlUsd is between 0 and -1e6");
1529 | | }
1530 | * | if (basePnlUsd < -1e6 && basePnlUsd >= -1e12) {
1531 | | fl.log("PositionInfo basePnlUsd is between -1e6 and -1e12");
1532 | | }
1533 | * | if (basePnlUsd < -1e12 && basePnlUsd >= -1e18) {
1534 | * | fl.log("PositionInfo basePnlUsd is between -1e12 and -1e18");
1535 | | }
1536 | * | if (basePnlUsd < -1e18 && basePnlUsd >= -1e24) {
1537 | * | fl.log("PositionInfo basePnlUsd is between -1e18 and -1e24");
1538 | | }
1539 | * | if (basePnlUsd < -1e24) {
1540 | * | fl.log("PositionInfo basePnlUsd is less than -1e24");
1541 | | }
1542 | | }
1543 | * | function _logPositionInfoUncappedBasePnlUsdCoverage(
1544 | | int256 uncappedBasePnlUsd
1545 | | ) internal {
1546 | * | if (uncappedBasePnlUsd == 0) {
1547 | * | fl.log("PositionInfo uncappedBasePnlUsd is 0");
1548 | | }
1549 | * | if (uncappedBasePnlUsd > 0 && uncappedBasePnlUsd <= 1e6) {
1550 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and 1e6");
1551 | | }
1552 | * | if (uncappedBasePnlUsd > 1e6 && uncappedBasePnlUsd <= 1e12) {
1553 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e6 and 1e12");
1554 | | }
1555 | * | if (uncappedBasePnlUsd > 1e12 && uncappedBasePnlUsd <= 1e18) {
1556 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e12 and 1e18");
1557 | | }
1558 | * | if (uncappedBasePnlUsd > 1e18 && uncappedBasePnlUsd <= 1e24) {
1559 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e18 and 1e24");
1560 | | }
1561 | * | if (uncappedBasePnlUsd > 1e24) {
1562 | * | fl.log("PositionInfo uncappedBasePnlUsd is greater than 1e24");
1563 | | }
1564 | * | if (uncappedBasePnlUsd < 0 && uncappedBasePnlUsd >= -1e6) {
1565 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and -1e6");
1566 | | }
1567 | * | if (uncappedBasePnlUsd < -1e6 && uncappedBasePnlUsd >= -1e12) {
1568 | | fl.log("PositionInfo uncappedBasePnlUsd is between -1e6 and -1e12");
1569 | | }
1570 | * | if (uncappedBasePnlUsd < -1e12 && uncappedBasePnlUsd >= -1e18) {
1571 | * | fl.log(
1572 | | "PositionInfo uncappedBasePnlUsd is between -1e12 and -1e18"
1573 | | );
1574 | | }
1575 | * | if (uncappedBasePnlUsd < -1e18 && uncappedBasePnlUsd >= -1e24) {
1576 | * | fl.log(
1577 | | "PositionInfo uncappedBasePnlUsd is between -1e18 and -1e24"
1578 | | );
1579 | | }
1580 | * | if (uncappedBasePnlUsd < -1e24) {
1581 | * | fl.log("PositionInfo uncappedBasePnlUsd is less than -1e24");
1582 | | }
1583 | | }
1584 | * | function _logPositionInfoPnlAfterPriceImpactUsdCoverage(
1585 | | int256 pnlAfterPriceImpactUsd
1586 | | ) internal {
1587 | * | if (pnlAfterPriceImpactUsd == 0) {
1588 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is 0");
1589 | | }
1590 | * | if (pnlAfterPriceImpactUsd > 0 && pnlAfterPriceImpactUsd <= 1e6) {
1591 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and 1e6");
1592 | | }
1593 | * | if (pnlAfterPriceImpactUsd > 1e6 && pnlAfterPriceImpactUsd <= 1e12) {
1594 | | fl.log(
1595 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e6 and 1e12"
1596 | | );
1597 | | }
1598 | * | if (pnlAfterPriceImpactUsd > 1e12 && pnlAfterPriceImpactUsd <= 1e18) {
1599 | | fl.log(
1600 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e12 and 1e18"
1601 | | );
1602 | | }
1603 | * | if (pnlAfterPriceImpactUsd > 1e18 && pnlAfterPriceImpactUsd <= 1e24) {
1604 | | fl.log(
1605 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e18 and 1e24"
1606 | | );
1607 | | }
1608 | * | if (pnlAfterPriceImpactUsd > 1e24) {
1609 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is greater than 1e24");
1610 | | }
1611 | * | if (pnlAfterPriceImpactUsd < 0 && pnlAfterPriceImpactUsd >= -1e6) {
1612 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and -1e6");
1613 | | }
1614 | * | if (pnlAfterPriceImpactUsd < -1e6 && pnlAfterPriceImpactUsd >= -1e12) {
1615 | | fl.log(
1616 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e6 and -1e12"
1617 | | );
1618 | | }
1619 | * | if (pnlAfterPriceImpactUsd < -1e12 && pnlAfterPriceImpactUsd >= -1e18) {
1620 | * | fl.log(
1621 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e12 and -1e18"
1622 | | );
1623 | | }
1624 | * | if (pnlAfterPriceImpactUsd < -1e18 && pnlAfterPriceImpactUsd >= -1e24) {
1625 | * | fl.log(
1626 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e18 and -1e24"
1627 | | );
1628 | | }
1629 | * | if (pnlAfterPriceImpactUsd < -1e24) {
1630 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is less than -1e24");
1631 | | }
1632 | | }
1633 | | }
1634 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/IncreasePositionMarketCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract IncreasePositionMarketCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ INCREASE POSITION
10 | | // __^ __( \.__) ) GET MARKET INFO
11 | | // (@)<_____>__(_____)____/ COVERAGE
12 | |
13 | * | function _checkIncreaseOrderAndGetMarketInfoCoverage(
14 | | ReaderUtils.MarketInfo memory marketInfo
15 | | ) internal {
16 | * | _logMarketInfoMarketTokenCoverage(marketInfo.market.marketToken);
17 | * | _logMarketInfoIndexTokenCoverage(marketInfo.market.indexToken);
18 | * | _logMarketInfoLongTokenCoverage(marketInfo.market.longToken);
19 | * | _logMarketInfoShortTokenCoverage(marketInfo.market.shortToken);
20 | * | _logMarketInfoBorrowingFactorPerSecondForLongsCoverage(
21 | * | marketInfo.borrowingFactorPerSecondForLongs
22 | | );
23 | * | _logMarketInfoBorrowingFactorPerSecondForShortsCoverage(
24 | * | marketInfo.borrowingFactorPerSecondForShorts
25 | | );
26 | * | _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage(
27 | * | marketInfo.baseFunding.fundingFeeAmountPerSize.long
28 | | );
29 | * | _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage(
30 | * | marketInfo.baseFunding.fundingFeeAmountPerSize.short
31 | | );
32 | * | _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage(
33 | * | marketInfo.baseFunding.claimableFundingAmountPerSize.long
34 | | );
35 | * | _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage(
36 | * | marketInfo.baseFunding.claimableFundingAmountPerSize.short
37 | | );
38 | * | _logMarketInfoNextFundingLongsPayShortsCoverage(
39 | * | marketInfo.nextFunding.longsPayShorts
40 | | );
41 | * | _logMarketInfoNextFundingFundingFactorPerSecondCoverage(
42 | * | marketInfo.nextFunding.fundingFactorPerSecond
43 | | );
44 | * | _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage(
45 | * | marketInfo.nextFunding.nextSavedFundingFactorPerSecond
46 | | );
47 | * | _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage(
48 | * | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.long
49 | | );
50 | * | _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage(
51 | * | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.short
52 | | );
53 | * | _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage(
54 | * | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.long
55 | | );
56 | * | _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage(
57 | * | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.short
58 | | );
59 | * | _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage(
60 | * | marketInfo.virtualInventory.virtualPoolAmountForLongToken
61 | | );
62 | * | _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage(
63 | * | marketInfo.virtualInventory.virtualPoolAmountForShortToken
64 | | );
65 | * | _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage(
66 | * | marketInfo.virtualInventory.virtualInventoryForPositions
67 | | );
68 | * | _logMarketInfoIsDisabledCoverage(marketInfo.isDisabled);
69 | | }
70 | |
71 | * | function _logMarketInfoMarketTokenCoverage(address marketToken) internal {
72 | * | if (marketToken == address(market_0_WETH_USDC)) {
73 | | fl.log("MarketInfo marketToken market_0_WETH_USDC hit");
74 | | }
75 | |
76 | * | if (marketToken == address(market_WBTC_WBTC_USDC)) {
77 | * | fl.log("MarketInfo marketToken market_WBTC_WBTC_USDC hit");
78 | | }
79 | * | if (marketToken == address(market_WETH_WETH_USDC)) {
80 | * | fl.log("MarketInfo marketToken market_WETH_WETH_USDC hit");
81 | | }
82 | * | if (marketToken == address(market_WETH_WETH_USDT)) {
83 | * | fl.log("MarketInfo marketToken market_WETH_WETH_USDT hit");
84 | | }
85 | | }
86 | |
87 | * | function _logMarketInfoIndexTokenCoverage(address indexToken) internal {
88 | * | if (indexToken == address(0)) {
89 | | fl.log("MarketInfo indexToken is address(0)");
90 | | } else {
91 | * | fl.log("MarketInfo indexToken is non-zero address");
92 | | }
93 | | }
94 | |
95 | * | function _logMarketInfoLongTokenCoverage(address longToken) internal {
96 | * | if (longToken == address(0)) {
97 | | fl.log("MarketInfo longToken is address(0)");
98 | | } else {
99 | * | fl.log("MarketInfo longToken is non-zero address");
100 | | }
101 | | }
102 | |
103 | * | function _logMarketInfoShortTokenCoverage(address shortToken) internal {
104 | * | if (shortToken == address(0)) {
105 | | fl.log("MarketInfo shortToken is address(0)");
106 | | } else {
107 | * | fl.log("MarketInfo shortToken is non-zero address");
108 | | }
109 | | }
110 | |
111 | * | function _logMarketInfoBorrowingFactorPerSecondForLongsCoverage(
112 | | uint256 borrowingFactorPerSecondForLongs
113 | | ) internal {
114 | * | if (borrowingFactorPerSecondForLongs == 0) {
115 | * | fl.log("MarketInfo borrowingFactorPerSecondForLongs is 0");
116 | | }
117 | * | if (
118 | * | borrowingFactorPerSecondForLongs > 0 &&
119 | | borrowingFactorPerSecondForLongs <= 1e6
120 | | ) {
121 | | fl.log(
122 | | "MarketInfo borrowingFactorPerSecondForLongs is between 0 and 1e6"
123 | | );
124 | | }
125 | * | if (
126 | * | borrowingFactorPerSecondForLongs > 1e6 &&
127 | | borrowingFactorPerSecondForLongs <= 1e12
128 | | ) {
129 | | fl.log(
130 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e6 and 1e12"
131 | | );
132 | | }
133 | * | if (
134 | * | borrowingFactorPerSecondForLongs > 1e12 &&
135 | | borrowingFactorPerSecondForLongs <= 1e18
136 | | ) {
137 | | fl.log(
138 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e12 and 1e18"
139 | | );
140 | | }
141 | * | if (
142 | * | borrowingFactorPerSecondForLongs > 1e18 &&
143 | | borrowingFactorPerSecondForLongs <= 1e24
144 | | ) {
145 | | fl.log(
146 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e18 and 1e24"
147 | | );
148 | | }
149 | * | if (borrowingFactorPerSecondForLongs > 1e24) {
150 | | fl.log(
151 | | "MarketInfo borrowingFactorPerSecondForLongs is greater than 1e24"
152 | | );
153 | | }
154 | | }
155 | |
156 | * | function _logMarketInfoBorrowingFactorPerSecondForShortsCoverage(
157 | | uint256 borrowingFactorPerSecondForShorts
158 | | ) internal {
159 | * | if (borrowingFactorPerSecondForShorts == 0) {
160 | * | fl.log("MarketInfo borrowingFactorPerSecondForShorts is 0");
161 | | }
162 | * | if (
163 | * | borrowingFactorPerSecondForShorts > 0 &&
164 | | borrowingFactorPerSecondForShorts <= 1e6
165 | | ) {
166 | | fl.log(
167 | | "MarketInfo borrowingFactorPerSecondForShorts is between 0 and 1e6"
168 | | );
169 | | }
170 | * | if (
171 | * | borrowingFactorPerSecondForShorts > 1e6 &&
172 | | borrowingFactorPerSecondForShorts <= 1e12
173 | | ) {
174 | | fl.log(
175 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e6 and 1e12"
176 | | );
177 | | }
178 | * | if (
179 | * | borrowingFactorPerSecondForShorts > 1e12 &&
180 | | borrowingFactorPerSecondForShorts <= 1e18
181 | | ) {
182 | | fl.log(
183 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e12 and 1e18"
184 | | );
185 | | }
186 | * | if (
187 | * | borrowingFactorPerSecondForShorts > 1e18 &&
188 | | borrowingFactorPerSecondForShorts <= 1e24
189 | | ) {
190 | | fl.log(
191 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e18 and 1e24"
192 | | );
193 | | }
194 | * | if (borrowingFactorPerSecondForShorts > 1e24) {
195 | | fl.log(
196 | | "MarketInfo borrowingFactorPerSecondForShorts is greater than 1e24"
197 | | );
198 | | }
199 | | }
200 | |
201 | * | function _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage(
202 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSize
203 | | ) internal {
204 | * | if (
205 | * | longFundingFeeAmountPerSize.longToken == 0 &&
206 | * | longFundingFeeAmountPerSize.shortToken == 0
207 | | ) {
208 | * | fl.log(
209 | | "MarketInfo baseFunding longFundingFeeAmountPerSize is 0 for both longToken and shortToken"
210 | | );
211 | | }
212 | * | if (
213 | * | longFundingFeeAmountPerSize.longToken > 0 &&
214 | * | longFundingFeeAmountPerSize.longToken <= 1e6
215 | | ) {
216 | | fl.log(
217 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 0 and 1e6"
218 | | );
219 | | }
220 | * | if (
221 | * | longFundingFeeAmountPerSize.longToken > 1e6 &&
222 | * | longFundingFeeAmountPerSize.longToken <= 1e12
223 | | ) {
224 | | fl.log(
225 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e6 and 1e12"
226 | | );
227 | | }
228 | * | if (
229 | * | longFundingFeeAmountPerSize.longToken > 1e12 &&
230 | * | longFundingFeeAmountPerSize.longToken <= 1e18
231 | | ) {
232 | * | fl.log(
233 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e12 and 1e18"
234 | | );
235 | | }
236 | * | if (
237 | * | longFundingFeeAmountPerSize.longToken > 1e18 &&
238 | * | longFundingFeeAmountPerSize.longToken <= 1e24
239 | | ) {
240 | * | fl.log(
241 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e18 and 1e24"
242 | | );
243 | | }
244 | * | if (longFundingFeeAmountPerSize.longToken > 1e24) {
245 | * | fl.log(
246 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is greater than 1e24"
247 | | );
248 | | }
249 | * | if (
250 | * | longFundingFeeAmountPerSize.shortToken > 0 &&
251 | * | longFundingFeeAmountPerSize.shortToken <= 1e6
252 | | ) {
253 | | fl.log(
254 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 0 and 1e6"
255 | | );
256 | | }
257 | * | if (
258 | * | longFundingFeeAmountPerSize.shortToken > 1e6 &&
259 | * | longFundingFeeAmountPerSize.shortToken <= 1e12
260 | | ) {
261 | | fl.log(
262 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e6 and 1e12"
263 | | );
264 | | }
265 | * | if (
266 | * | longFundingFeeAmountPerSize.shortToken > 1e12 &&
267 | * | longFundingFeeAmountPerSize.shortToken <= 1e18
268 | | ) {
269 | | fl.log(
270 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e12 and 1e18"
271 | | );
272 | | }
273 | * | if (
274 | * | longFundingFeeAmountPerSize.shortToken > 1e18 &&
275 | * | longFundingFeeAmountPerSize.shortToken <= 1e24
276 | | ) {
277 | * | fl.log(
278 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e18 and 1e24"
279 | | );
280 | | }
281 | * | if (longFundingFeeAmountPerSize.shortToken > 1e24) {
282 | | fl.log(
283 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is greater than 1e24"
284 | | );
285 | | }
286 | | }
287 | |
288 | * | function _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage(
289 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSize
290 | | ) internal {
291 | * | if (
292 | * | shortFundingFeeAmountPerSize.longToken == 0 &&
293 | * | shortFundingFeeAmountPerSize.shortToken == 0
294 | | ) {
295 | * | fl.log(
296 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize is 0 for both longToken and shortToken"
297 | | );
298 | | }
299 | * | if (
300 | * | shortFundingFeeAmountPerSize.longToken > 0 &&
301 | | shortFundingFeeAmountPerSize.longToken <= 1e6
302 | | ) {
303 | | fl.log(
304 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 0 and 1e6"
305 | | );
306 | | }
307 | * | if (
308 | * | shortFundingFeeAmountPerSize.longToken > 1e6 &&
309 | | shortFundingFeeAmountPerSize.longToken <= 1e12
310 | | ) {
311 | | fl.log(
312 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e6 and 1e12"
313 | | );
314 | | }
315 | * | if (
316 | * | shortFundingFeeAmountPerSize.longToken > 1e12 &&
317 | | shortFundingFeeAmountPerSize.longToken <= 1e18
318 | | ) {
319 | | fl.log(
320 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e12 and 1e18"
321 | | );
322 | | }
323 | * | if (
324 | * | shortFundingFeeAmountPerSize.longToken > 1e18 &&
325 | | shortFundingFeeAmountPerSize.longToken <= 1e24
326 | | ) {
327 | | fl.log(
328 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e18 and 1e24"
329 | | );
330 | | }
331 | * | if (shortFundingFeeAmountPerSize.longToken > 1e24) {
332 | | fl.log(
333 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is greater than 1e24"
334 | | );
335 | | }
336 | * | if (
337 | * | shortFundingFeeAmountPerSize.shortToken > 0 &&
338 | * | shortFundingFeeAmountPerSize.shortToken <= 1e6
339 | | ) {
340 | | fl.log(
341 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 0 and 1e6"
342 | | );
343 | | }
344 | * | if (
345 | * | shortFundingFeeAmountPerSize.shortToken > 1e6 &&
346 | * | shortFundingFeeAmountPerSize.shortToken <= 1e12
347 | | ) {
348 | | fl.log(
349 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e6 and 1e12"
350 | | );
351 | | }
352 | * | if (
353 | * | shortFundingFeeAmountPerSize.shortToken > 1e12 &&
354 | * | shortFundingFeeAmountPerSize.shortToken <= 1e18
355 | | ) {
356 | * | fl.log(
357 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e12 and 1e18"
358 | | );
359 | | }
360 | * | if (
361 | * | shortFundingFeeAmountPerSize.shortToken > 1e18 &&
362 | * | shortFundingFeeAmountPerSize.shortToken <= 1e24
363 | | ) {
364 | * | fl.log(
365 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e18 and 1e24"
366 | | );
367 | | }
368 | * | if (shortFundingFeeAmountPerSize.shortToken > 1e24) {
369 | | fl.log(
370 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is greater than 1e24"
371 | | );
372 | | }
373 | | }
374 | |
375 | * | function _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage(
376 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSize
377 | | ) internal {
378 | * | if (
379 | * | longClaimableFundingAmountPerSize.longToken == 0 &&
380 | * | longClaimableFundingAmountPerSize.shortToken == 0
381 | | ) {
382 | * | fl.log(
383 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize is 0 for both longToken and shortToken"
384 | | );
385 | | }
386 | * | if (
387 | * | longClaimableFundingAmountPerSize.longToken > 0 &&
388 | | longClaimableFundingAmountPerSize.longToken <= 1e6
389 | | ) {
390 | | fl.log(
391 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 0 and 1e6"
392 | | );
393 | | }
394 | * | if (
395 | * | longClaimableFundingAmountPerSize.longToken > 1e6 &&
396 | | longClaimableFundingAmountPerSize.longToken <= 1e12
397 | | ) {
398 | | fl.log(
399 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e6 and 1e12"
400 | | );
401 | | }
402 | * | if (
403 | * | longClaimableFundingAmountPerSize.longToken > 1e12 &&
404 | | longClaimableFundingAmountPerSize.longToken <= 1e18
405 | | ) {
406 | | fl.log(
407 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e12 and 1e18"
408 | | );
409 | | }
410 | * | if (
411 | * | longClaimableFundingAmountPerSize.longToken > 1e18 &&
412 | | longClaimableFundingAmountPerSize.longToken <= 1e24
413 | | ) {
414 | | fl.log(
415 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e18 and 1e24"
416 | | );
417 | | }
418 | * | if (longClaimableFundingAmountPerSize.longToken > 1e24) {
419 | | fl.log(
420 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is greater than 1e24"
421 | | );
422 | | }
423 | * | if (
424 | * | longClaimableFundingAmountPerSize.shortToken > 0 &&
425 | * | longClaimableFundingAmountPerSize.shortToken <= 1e6
426 | | ) {
427 | | fl.log(
428 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 0 and 1e6"
429 | | );
430 | | }
431 | * | if (
432 | * | longClaimableFundingAmountPerSize.shortToken > 1e6 &&
433 | * | longClaimableFundingAmountPerSize.shortToken <= 1e12
434 | | ) {
435 | | fl.log(
436 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12"
437 | | );
438 | | }
439 | * | if (
440 | * | longClaimableFundingAmountPerSize.shortToken > 1e12 &&
441 | * | longClaimableFundingAmountPerSize.shortToken <= 1e18
442 | | ) {
443 | | fl.log(
444 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18"
445 | | );
446 | | }
447 | * | if (
448 | * | longClaimableFundingAmountPerSize.shortToken > 1e18 &&
449 | * | longClaimableFundingAmountPerSize.shortToken <= 1e24
450 | | ) {
451 | * | fl.log(
452 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24"
453 | | );
454 | | }
455 | * | if (longClaimableFundingAmountPerSize.shortToken > 1e24) {
456 | * | fl.log(
457 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is greater than 1e24"
458 | | );
459 | | }
460 | | }
461 | |
462 | * | function _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage(
463 | | MarketUtils.CollateralType memory shortClaimableFundingAmountPerSize
464 | | ) internal {
465 | * | if (
466 | * | shortClaimableFundingAmountPerSize.longToken == 0 &&
467 | * | shortClaimableFundingAmountPerSize.shortToken == 0
468 | | ) {
469 | * | fl.log(
470 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize is 0 for both longToken and shortToken"
471 | | );
472 | | }
473 | * | if (
474 | * | shortClaimableFundingAmountPerSize.longToken > 0 &&
475 | * | shortClaimableFundingAmountPerSize.longToken <= 1e6
476 | | ) {
477 | | fl.log(
478 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 0 and 1e6"
479 | | );
480 | | }
481 | * | if (
482 | * | shortClaimableFundingAmountPerSize.longToken > 1e6 &&
483 | * | shortClaimableFundingAmountPerSize.longToken <= 1e12
484 | | ) {
485 | | fl.log(
486 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e6 and 1e12"
487 | | );
488 | | }
489 | * | if (
490 | * | shortClaimableFundingAmountPerSize.longToken > 1e12 &&
491 | * | shortClaimableFundingAmountPerSize.longToken <= 1e18
492 | | ) {
493 | * | fl.log(
494 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e12 and 1e18"
495 | | );
496 | | }
497 | * | if (
498 | * | shortClaimableFundingAmountPerSize.longToken > 1e18 &&
499 | * | shortClaimableFundingAmountPerSize.longToken <= 1e24
500 | | ) {
501 | * | fl.log(
502 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e18 and 1e24"
503 | | );
504 | | }
505 | * | if (shortClaimableFundingAmountPerSize.longToken > 1e24) {
506 | * | fl.log(
507 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is greater than 1e24"
508 | | );
509 | | }
510 | * | if (
511 | * | shortClaimableFundingAmountPerSize.shortToken > 0 &&
512 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e6
513 | | ) {
514 | | fl.log(
515 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 0 and 1e6"
516 | | );
517 | | }
518 | * | if (
519 | * | shortClaimableFundingAmountPerSize.shortToken > 1e6 &&
520 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e12
521 | | ) {
522 | | fl.log(
523 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12"
524 | | );
525 | | }
526 | * | if (
527 | * | shortClaimableFundingAmountPerSize.shortToken > 1e12 &&
528 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e18
529 | | ) {
530 | * | fl.log(
531 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18"
532 | | );
533 | | }
534 | * | if (
535 | * | shortClaimableFundingAmountPerSize.shortToken > 1e18 &&
536 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e24
537 | | ) {
538 | * | fl.log(
539 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24"
540 | | );
541 | | }
542 | * | if (shortClaimableFundingAmountPerSize.shortToken > 1e24) {
543 | * | fl.log(
544 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is greater than 1e24"
545 | | );
546 | | }
547 | | }
548 | |
549 | * | function _logMarketInfoNextFundingLongsPayShortsCoverage(
550 | | bool longsPayShorts
551 | | ) internal {
552 | * | if (longsPayShorts) {
553 | * | fl.log("MarketInfo nextFunding longsPayShorts is true");
554 | | } else {
555 | * | fl.log("MarketInfo nextFunding longsPayShorts is false");
556 | | }
557 | | }
558 | |
559 | * | function _logMarketInfoNextFundingFundingFactorPerSecondCoverage(
560 | | uint256 fundingFactorPerSecond
561 | | ) internal {
562 | * | if (fundingFactorPerSecond == 0) {
563 | * | fl.log("MarketInfo nextFunding fundingFactorPerSecond is 0");
564 | | }
565 | * | if (fundingFactorPerSecond > 0 && fundingFactorPerSecond <= 1e6) {
566 | | fl.log(
567 | | "MarketInfo nextFunding fundingFactorPerSecond is between 0 and 1e6"
568 | | );
569 | | }
570 | * | if (fundingFactorPerSecond > 1e6 && fundingFactorPerSecond <= 1e12) {
571 | | fl.log(
572 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e6 and 1e12"
573 | | );
574 | | }
575 | * | if (fundingFactorPerSecond > 1e12 && fundingFactorPerSecond <= 1e18) {
576 | | fl.log(
577 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e12 and 1e18"
578 | | );
579 | | }
580 | * | if (fundingFactorPerSecond > 1e18 && fundingFactorPerSecond <= 1e24) {
581 | * | fl.log(
582 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e18 and 1e24"
583 | | );
584 | | }
585 | * | if (fundingFactorPerSecond > 1e24) {
586 | * | fl.log(
587 | | "MarketInfo nextFunding fundingFactorPerSecond is greater than 1e24"
588 | | );
589 | | }
590 | | }
591 | |
592 | * | function _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage(
593 | | int256 nextSavedFundingFactorPerSecond
594 | | ) internal {
595 | * | if (nextSavedFundingFactorPerSecond == 0) {
596 | * | fl.log(
597 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is 0"
598 | | );
599 | | }
600 | * | if (
601 | * | nextSavedFundingFactorPerSecond > 0 &&
602 | | nextSavedFundingFactorPerSecond <= 1e6
603 | | ) {
604 | | fl.log(
605 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and 1e6"
606 | | );
607 | | }
608 | * | if (
609 | * | nextSavedFundingFactorPerSecond > 1e6 &&
610 | | nextSavedFundingFactorPerSecond <= 1e12
611 | | ) {
612 | | fl.log(
613 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e6 and 1e12"
614 | | );
615 | | }
616 | * | if (
617 | * | nextSavedFundingFactorPerSecond > 1e12 &&
618 | | nextSavedFundingFactorPerSecond <= 1e18
619 | | ) {
620 | | fl.log(
621 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e12 and 1e18"
622 | | );
623 | | }
624 | * | if (
625 | * | nextSavedFundingFactorPerSecond > 1e18 &&
626 | | nextSavedFundingFactorPerSecond <= 1e24
627 | | ) {
628 | | fl.log(
629 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e18 and 1e24"
630 | | );
631 | | }
632 | * | if (nextSavedFundingFactorPerSecond > 1e24) {
633 | | fl.log(
634 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is greater than 1e24"
635 | | );
636 | | }
637 | * | if (
638 | * | nextSavedFundingFactorPerSecond < 0 &&
639 | | nextSavedFundingFactorPerSecond >= -1e6
640 | | ) {
641 | | fl.log(
642 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and -1e6"
643 | | );
644 | | }
645 | * | if (
646 | * | nextSavedFundingFactorPerSecond < -1e6 &&
647 | | nextSavedFundingFactorPerSecond >= -1e12
648 | | ) {
649 | | fl.log(
650 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e6 and -1e12"
651 | | );
652 | | }
653 | * | if (
654 | * | nextSavedFundingFactorPerSecond < -1e12 &&
655 | | nextSavedFundingFactorPerSecond >= -1e18
656 | | ) {
657 | | fl.log(
658 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e12 and -1e18"
659 | | );
660 | | }
661 | * | if (
662 | * | nextSavedFundingFactorPerSecond < -1e18 &&
663 | | nextSavedFundingFactorPerSecond >= -1e24
664 | | ) {
665 | | fl.log(
666 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e18 and -1e24"
667 | | );
668 | | }
669 | * | if (nextSavedFundingFactorPerSecond < -1e24) {
670 | | fl.log(
671 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is less than -1e24"
672 | | );
673 | | }
674 | | }
675 | |
676 | * | function _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage(
677 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSizeDelta
678 | | ) internal {
679 | * | if (
680 | * | longFundingFeeAmountPerSizeDelta.longToken == 0 &&
681 | * | longFundingFeeAmountPerSizeDelta.shortToken == 0
682 | | ) {
683 | * | fl.log(
684 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken"
685 | | );
686 | | }
687 | * | if (
688 | * | longFundingFeeAmountPerSizeDelta.longToken > 0 &&
689 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e6
690 | | ) {
691 | | fl.log(
692 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6"
693 | | );
694 | | }
695 | * | if (
696 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e6 &&
697 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e12
698 | | ) {
699 | | fl.log(
700 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12"
701 | | );
702 | | }
703 | * | if (
704 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e12 &&
705 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e18
706 | | ) {
707 | * | fl.log(
708 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18"
709 | | );
710 | | }
711 | * | if (
712 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e18 &&
713 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e24
714 | | ) {
715 | | fl.log(
716 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24"
717 | | );
718 | | }
719 | * | if (longFundingFeeAmountPerSizeDelta.longToken > 1e24) {
720 | * | fl.log(
721 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is greater than 1e24"
722 | | );
723 | | }
724 | * | if (
725 | * | longFundingFeeAmountPerSizeDelta.shortToken > 0 &&
726 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e6
727 | | ) {
728 | | fl.log(
729 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6"
730 | | );
731 | | }
732 | * | if (
733 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e6 &&
734 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e12
735 | | ) {
736 | | fl.log(
737 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12"
738 | | );
739 | | }
740 | * | if (
741 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e12 &&
742 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e18
743 | | ) {
744 | * | fl.log(
745 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18"
746 | | );
747 | | }
748 | * | if (
749 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e18 &&
750 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e24
751 | | ) {
752 | * | fl.log(
753 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24"
754 | | );
755 | | }
756 | * | if (longFundingFeeAmountPerSizeDelta.shortToken > 1e24) {
757 | | fl.log(
758 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is greater than 1e24"
759 | | );
760 | | }
761 | | }
762 | * | function _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage(
763 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSizeDelta
764 | | ) internal {
765 | * | if (
766 | * | shortFundingFeeAmountPerSizeDelta.longToken == 0 &&
767 | * | shortFundingFeeAmountPerSizeDelta.shortToken == 0
768 | | ) {
769 | * | fl.log(
770 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken"
771 | | );
772 | | }
773 | * | if (
774 | * | shortFundingFeeAmountPerSizeDelta.longToken > 0 &&
775 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e6
776 | | ) {
777 | | fl.log(
778 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6"
779 | | );
780 | | }
781 | * | if (
782 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e6 &&
783 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e12
784 | | ) {
785 | | fl.log(
786 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12"
787 | | );
788 | | }
789 | * | if (
790 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e12 &&
791 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e18
792 | | ) {
793 | | fl.log(
794 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18"
795 | | );
796 | | }
797 | * | if (
798 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e18 &&
799 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e24
800 | | ) {
801 | | fl.log(
802 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24"
803 | | );
804 | | }
805 | * | if (shortFundingFeeAmountPerSizeDelta.longToken > 1e24) {
806 | | fl.log(
807 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is greater than 1e24"
808 | | );
809 | | }
810 | * | if (
811 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 0 &&
812 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e6
813 | | ) {
814 | | fl.log(
815 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6"
816 | | );
817 | | }
818 | * | if (
819 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e6 &&
820 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e12
821 | | ) {
822 | | fl.log(
823 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12"
824 | | );
825 | | }
826 | * | if (
827 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e12 &&
828 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e18
829 | | ) {
830 | * | fl.log(
831 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18"
832 | | );
833 | | }
834 | * | if (
835 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e18 &&
836 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e24
837 | | ) {
838 | * | fl.log(
839 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24"
840 | | );
841 | | }
842 | * | if (shortFundingFeeAmountPerSizeDelta.shortToken > 1e24) {
843 | | fl.log(
844 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is greater than 1e24"
845 | | );
846 | | }
847 | | }
848 | |
849 | * | function _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage(
850 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSizeDelta
851 | | ) internal {
852 | * | if (
853 | * | longClaimableFundingAmountPerSizeDelta.longToken == 0 &&
854 | * | longClaimableFundingAmountPerSizeDelta.shortToken == 0
855 | | ) {
856 | * | fl.log(
857 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken"
858 | | );
859 | | }
860 | * | if (
861 | * | longClaimableFundingAmountPerSizeDelta.longToken > 0 &&
862 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e6
863 | | ) {
864 | | fl.log(
865 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6"
866 | | );
867 | | }
868 | * | if (
869 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e6 &&
870 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e12
871 | | ) {
872 | | fl.log(
873 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12"
874 | | );
875 | | }
876 | * | if (
877 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e12 &&
878 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e18
879 | | ) {
880 | | fl.log(
881 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18"
882 | | );
883 | | }
884 | * | if (
885 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e18 &&
886 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e24
887 | | ) {
888 | | fl.log(
889 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24"
890 | | );
891 | | }
892 | * | if (longClaimableFundingAmountPerSizeDelta.longToken > 1e24) {
893 | | fl.log(
894 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is greater than 1e24"
895 | | );
896 | | }
897 | * | if (
898 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 0 &&
899 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e6
900 | | ) {
901 | | fl.log(
902 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6"
903 | | );
904 | | }
905 | * | if (
906 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e6 &&
907 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e12
908 | | ) {
909 | | fl.log(
910 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12"
911 | | );
912 | | }
913 | * | if (
914 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e12 &&
915 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e18
916 | | ) {
917 | * | fl.log(
918 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18"
919 | | );
920 | | }
921 | * | if (
922 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e18 &&
923 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e24
924 | | ) {
925 | * | fl.log(
926 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24"
927 | | );
928 | | }
929 | * | if (longClaimableFundingAmountPerSizeDelta.shortToken > 1e24) {
930 | | fl.log(
931 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24"
932 | | );
933 | | }
934 | | }
935 | |
936 | * | function _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage(
937 | | MarketUtils.CollateralType
938 | | memory shortClaimableFundingAmountPerSizeDelta
939 | | ) internal {
940 | * | if (
941 | * | shortClaimableFundingAmountPerSizeDelta.longToken == 0 &&
942 | * | shortClaimableFundingAmountPerSizeDelta.shortToken == 0
943 | | ) {
944 | * | fl.log(
945 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken"
946 | | );
947 | | }
948 | * | if (
949 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 0 &&
950 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e6
951 | | ) {
952 | | fl.log(
953 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6"
954 | | );
955 | | }
956 | * | if (
957 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e6 &&
958 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e12
959 | | ) {
960 | | fl.log(
961 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12"
962 | | );
963 | | }
964 | * | if (
965 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e12 &&
966 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e18
967 | | ) {
968 | * | fl.log(
969 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18"
970 | | );
971 | | }
972 | * | if (
973 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e18 &&
974 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e24
975 | | ) {
976 | * | fl.log(
977 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24"
978 | | );
979 | | }
980 | * | if (shortClaimableFundingAmountPerSizeDelta.longToken > 1e24) {
981 | * | fl.log(
982 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is greater than 1e24"
983 | | );
984 | | }
985 | * | if (
986 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 0 &&
987 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e6
988 | | ) {
989 | | fl.log(
990 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6"
991 | | );
992 | | }
993 | * | if (
994 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e6 &&
995 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e12
996 | | ) {
997 | | fl.log(
998 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12"
999 | | );
1000 | | }
1001 | * | if (
1002 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e12 &&
1003 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e18
1004 | | ) {
1005 | * | fl.log(
1006 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18"
1007 | | );
1008 | | }
1009 | * | if (
1010 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e18 &&
1011 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e24
1012 | | ) {
1013 | * | fl.log(
1014 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24"
1015 | | );
1016 | | }
1017 | * | if (shortClaimableFundingAmountPerSizeDelta.shortToken > 1e24) {
1018 | * | fl.log(
1019 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24"
1020 | | );
1021 | | }
1022 | | }
1023 | |
1024 | * | function _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage(
1025 | | uint256 virtualPoolAmountForLongToken
1026 | | ) internal {
1027 | * | if (virtualPoolAmountForLongToken == 0) {
1028 | * | fl.log(
1029 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is 0"
1030 | | );
1031 | | }
1032 | * | if (
1033 | * | virtualPoolAmountForLongToken > 0 &&
1034 | | virtualPoolAmountForLongToken <= 1e6
1035 | | ) {
1036 | | fl.log(
1037 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 0 and 1e6"
1038 | | );
1039 | | }
1040 | * | if (
1041 | * | virtualPoolAmountForLongToken > 1e6 &&
1042 | | virtualPoolAmountForLongToken <= 1e12
1043 | | ) {
1044 | | fl.log(
1045 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e6 and 1e12"
1046 | | );
1047 | | }
1048 | * | if (
1049 | * | virtualPoolAmountForLongToken > 1e12 &&
1050 | | virtualPoolAmountForLongToken <= 1e18
1051 | | ) {
1052 | | fl.log(
1053 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e12 and 1e18"
1054 | | );
1055 | | }
1056 | * | if (
1057 | * | virtualPoolAmountForLongToken > 1e18 &&
1058 | | virtualPoolAmountForLongToken <= 1e24
1059 | | ) {
1060 | | fl.log(
1061 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e18 and 1e24"
1062 | | );
1063 | | }
1064 | * | if (virtualPoolAmountForLongToken > 1e24) {
1065 | | fl.log(
1066 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is greater than 1e24"
1067 | | );
1068 | | }
1069 | | }
1070 | |
1071 | * | function _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage(
1072 | | uint256 virtualPoolAmountForShortToken
1073 | | ) internal {
1074 | * | if (virtualPoolAmountForShortToken == 0) {
1075 | * | fl.log(
1076 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is 0"
1077 | | );
1078 | | }
1079 | * | if (
1080 | * | virtualPoolAmountForShortToken > 0 &&
1081 | | virtualPoolAmountForShortToken <= 1e6
1082 | | ) {
1083 | | fl.log(
1084 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 0 and 1e6"
1085 | | );
1086 | | }
1087 | * | if (
1088 | * | virtualPoolAmountForShortToken > 1e6 &&
1089 | | virtualPoolAmountForShortToken <= 1e12
1090 | | ) {
1091 | | fl.log(
1092 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e6 and 1e12"
1093 | | );
1094 | | }
1095 | * | if (
1096 | * | virtualPoolAmountForShortToken > 1e12 &&
1097 | | virtualPoolAmountForShortToken <= 1e18
1098 | | ) {
1099 | | fl.log(
1100 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e12 and 1e18"
1101 | | );
1102 | | }
1103 | * | if (
1104 | * | virtualPoolAmountForShortToken > 1e18 &&
1105 | | virtualPoolAmountForShortToken <= 1e24
1106 | | ) {
1107 | | fl.log(
1108 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e18 and 1e24"
1109 | | );
1110 | | }
1111 | * | if (virtualPoolAmountForShortToken > 1e24) {
1112 | | fl.log(
1113 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is greater than 1e24"
1114 | | );
1115 | | }
1116 | | }
1117 | |
1118 | * | function _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage(
1119 | | int256 virtualInventoryForPositions
1120 | | ) internal {
1121 | * | if (virtualInventoryForPositions == 0) {
1122 | * | fl.log(
1123 | | "MarketInfo virtualInventory virtualInventoryForPositions is 0"
1124 | | );
1125 | | }
1126 | * | if (
1127 | * | virtualInventoryForPositions > 0 &&
1128 | | virtualInventoryForPositions <= 1e6
1129 | | ) {
1130 | | fl.log(
1131 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and 1e6"
1132 | | );
1133 | | }
1134 | * | if (
1135 | * | virtualInventoryForPositions > 1e6 &&
1136 | | virtualInventoryForPositions <= 1e12
1137 | | ) {
1138 | | fl.log(
1139 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e6 and 1e12"
1140 | | );
1141 | | }
1142 | * | if (
1143 | * | virtualInventoryForPositions > 1e12 &&
1144 | | virtualInventoryForPositions <= 1e18
1145 | | ) {
1146 | | fl.log(
1147 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e12 and 1e18"
1148 | | );
1149 | | }
1150 | * | if (
1151 | * | virtualInventoryForPositions > 1e18 &&
1152 | | virtualInventoryForPositions <= 1e24
1153 | | ) {
1154 | | fl.log(
1155 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e18 and 1e24"
1156 | | );
1157 | | }
1158 | * | if (virtualInventoryForPositions > 1e24) {
1159 | | fl.log(
1160 | | "MarketInfo virtualInventory virtualInventoryForPositions is greater than 1e24"
1161 | | );
1162 | | }
1163 | * | if (
1164 | * | virtualInventoryForPositions < 0 &&
1165 | | virtualInventoryForPositions >= -1e6
1166 | | ) {
1167 | | fl.log(
1168 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and -1e6"
1169 | | );
1170 | | }
1171 | * | if (
1172 | * | virtualInventoryForPositions < -1e6 &&
1173 | | virtualInventoryForPositions >= -1e12
1174 | | ) {
1175 | | fl.log(
1176 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e6 and -1e12"
1177 | | );
1178 | | }
1179 | * | if (
1180 | * | virtualInventoryForPositions < -1e12 &&
1181 | | virtualInventoryForPositions >= -1e18
1182 | | ) {
1183 | | fl.log(
1184 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e12 and -1e18"
1185 | | );
1186 | | }
1187 | * | if (
1188 | * | virtualInventoryForPositions < -1e18 &&
1189 | | virtualInventoryForPositions >= -1e24
1190 | | ) {
1191 | | fl.log(
1192 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e18 and -1e24"
1193 | | );
1194 | | }
1195 | * | if (virtualInventoryForPositions < -1e24) {
1196 | | fl.log(
1197 | | "MarketInfo virtualInventory virtualInventoryForPositions is less than -1e24"
1198 | | );
1199 | | }
1200 | | }
1201 | |
1202 | * | function _logMarketInfoIsDisabledCoverage(bool isDisabled) internal {
1203 | * | if (isDisabled) {
1204 | | fl.log("MarketInfo isDisabled is true");
1205 | | } else {
1206 | * | fl.log("MarketInfo isDisabled is false");
1207 | | }
1208 | | }
1209 | | }
1210 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftCancelCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract ShiftCancelCoverage is BeforeAfter {}
8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftCreatedCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract ShiftCreatedCoverage is BeforeAfter {}
8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftExecutedCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract ShiftExecutedCoverage is BeforeAfter {}
8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalCancelCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract WithdrawalCancelCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ CANCEL WITHDRAWAL COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | * | function _checkCancelWithdrawalCoverage(
14 | | Withdrawal.Props memory withdrawalProps
15 | | ) internal {
16 | * | _logWithdrawalAccountCoverage_cancelWithdrawal(
17 | * | withdrawalProps.addresses.account
18 | | );
19 | * | _logWithdrawalReceiverCoverage_cancelWithdrawal(
20 | * | withdrawalProps.addresses.receiver
21 | | );
22 | * | _logWithdrawalCallbackContractCoverage_cancelWithdrawal(
23 | * | withdrawalProps.addresses.callbackContract
24 | | );
25 | * | _logWithdrawalUiFeeReceiverCoverage_cancelWithdrawal(
26 | * | withdrawalProps.addresses.uiFeeReceiver
27 | | );
28 | * | _logWithdrawalMarketCoverage_cancelWithdrawal(
29 | * | withdrawalProps.addresses.market
30 | | );
31 | * | _logWithdrawalLongTokenSwapPathCoverage_cancelWithdrawal(
32 | * | withdrawalProps.addresses.longTokenSwapPath
33 | | );
34 | * | _logWithdrawalShortTokenSwapPathCoverage_cancelWithdrawal(
35 | * | withdrawalProps.addresses.shortTokenSwapPath
36 | | );
37 | * | _logWithdrawalMarketTokenAmountCoverage_cancelWithdrawal(
38 | * | withdrawalProps.numbers.marketTokenAmount
39 | | );
40 | * | _logWithdrawalMinLongTokenAmountCoverage_cancelWithdrawal(
41 | * | withdrawalProps.numbers.minLongTokenAmount
42 | | );
43 | * | _logWithdrawalMinShortTokenAmountCoverage_cancelWithdrawal(
44 | * | withdrawalProps.numbers.minShortTokenAmount
45 | | );
46 | * | _logWithdrawalUpdatedAtBlockCoverage_cancelWithdrawal(
47 | * | withdrawalProps.numbers.updatedAtBlock
48 | | );
49 | * | _logWithdrawalUpdatedAtTimeCoverage_cancelWithdrawal(
50 | * | withdrawalProps.numbers.updatedAtTime
51 | | );
52 | * | _logWithdrawalExecutionFeeCoverage_cancelWithdrawal(
53 | * | withdrawalProps.numbers.executionFee
54 | | );
55 | * | _logWithdrawalCallbackGasLimitCoverage_cancelWithdrawal(
56 | * | withdrawalProps.numbers.callbackGasLimit
57 | | );
58 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage_cancelWithdrawal(
59 | * | withdrawalProps.flags.shouldUnwrapNativeToken
60 | | );
61 | | }
62 | |
63 | * | function _logWithdrawalAccountCoverage_cancelWithdrawal(
64 | | address account
65 | | ) internal {
66 | * | if (account == USER0) {
67 | * | fl.log("Withdrawal account USER0 hit");
68 | | }
69 | * | if (account == USER1) {
70 | | fl.log("Withdrawal account USER1 hit");
71 | | }
72 | * | if (account == USER2) {
73 | | fl.log("Withdrawal account USER2 hit");
74 | | }
75 | * | if (account == USER3) {
76 | | fl.log("Withdrawal account USER3 hit");
77 | | }
78 | * | if (account == USER4) {
79 | | fl.log("Withdrawal account USER4 hit");
80 | | }
81 | * | if (account == USER5) {
82 | | fl.log("Withdrawal account USER5 hit");
83 | | }
84 | * | if (account == USER6) {
85 | | fl.log("Withdrawal account USER6 hit");
86 | | }
87 | * | if (account == USER7) {
88 | | fl.log("Withdrawal account USER7 hit");
89 | | }
90 | * | if (account == USER8) {
91 | | fl.log("Withdrawal account USER8 hit");
92 | | }
93 | * | if (account == USER9) {
94 | | fl.log("Withdrawal account USER9 hit");
95 | | }
96 | * | if (account == USER10) {
97 | | fl.log("Withdrawal account USER10 hit");
98 | | }
99 | * | if (account == USER11) {
100 | | fl.log("Withdrawal account USER11 hit");
101 | | }
102 | * | if (account == USER12) {
103 | | fl.log("Withdrawal account USER12 hit");
104 | | }
105 | * | if (account == USER13) {
106 | | fl.log("Withdrawal account USER13 hit");
107 | | }
108 | | }
109 | |
110 | * | function _logWithdrawalReceiverCoverage_cancelWithdrawal(
111 | | address receiver
112 | | ) internal {
113 | * | if (receiver == USER0) {
114 | * | fl.log("Withdrawal receiver USER0 hit");
115 | | }
116 | * | if (receiver == USER1) {
117 | | fl.log("Withdrawal receiver USER1 hit");
118 | | }
119 | * | if (receiver == USER2) {
120 | | fl.log("Withdrawal receiver USER2 hit");
121 | | }
122 | * | if (receiver == USER3) {
123 | | fl.log("Withdrawal receiver USER3 hit");
124 | | }
125 | * | if (receiver == USER4) {
126 | | fl.log("Withdrawal receiver USER4 hit");
127 | | }
128 | * | if (receiver == USER5) {
129 | | fl.log("Withdrawal receiver USER5 hit");
130 | | }
131 | * | if (receiver == USER6) {
132 | | fl.log("Withdrawal receiver USER6 hit");
133 | | }
134 | * | if (receiver == USER7) {
135 | | fl.log("Withdrawal receiver USER7 hit");
136 | | }
137 | * | if (receiver == USER8) {
138 | | fl.log("Withdrawal receiver USER8 hit");
139 | | }
140 | * | if (receiver == USER9) {
141 | | fl.log("Withdrawal receiver USER9 hit");
142 | | }
143 | * | if (receiver == USER10) {
144 | | fl.log("Withdrawal receiver USER10 hit");
145 | | }
146 | * | if (receiver == USER11) {
147 | | fl.log("Withdrawal receiver USER11 hit");
148 | | }
149 | * | if (receiver == USER12) {
150 | | fl.log("Withdrawal receiver USER12 hit");
151 | | }
152 | * | if (receiver == USER13) {
153 | | fl.log("Withdrawal receiver USER13 hit");
154 | | }
155 | | }
156 | * | function _logWithdrawalCallbackContractCoverage_cancelWithdrawal(
157 | | address callbackContract
158 | | ) internal {
159 | * | if (callbackContract == address(0)) {
160 | * | fl.log("Withdrawal callbackContract is address(0)");
161 | | } else {
162 | | fl.log("Withdrawal callbackContract is non-zero address");
163 | | }
164 | | }
165 | |
166 | * | function _logWithdrawalUiFeeReceiverCoverage_cancelWithdrawal(
167 | | address uiFeeReceiver
168 | | ) internal {
169 | * | if (uiFeeReceiver == address(0)) {
170 | * | fl.log("Withdrawal uiFeeReceiver is address(0)");
171 | | } else {
172 | | fl.log("Withdrawal uiFeeReceiver is non-zero address");
173 | | }
174 | | }
175 | |
176 | * | function _logWithdrawalMarketCoverage_cancelWithdrawal(
177 | | address market
178 | | ) internal {
179 | * | if (market == address(market_0_WETH_USDC)) {
180 | * | fl.log("Withdrawal market market_0_WETH_USDC hit");
181 | | }
182 | |
183 | * | if (market == address(market_WBTC_WBTC_USDC)) {
184 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit");
185 | | }
186 | * | if (market == address(market_WETH_WETH_USDC)) {
187 | * | fl.log("Withdrawal market market_WETH_WETH_USDC hit");
188 | | }
189 | * | if (market == address(market_WETH_WETH_USDT)) {
190 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit");
191 | | }
192 | | }
193 | |
194 | * | function _logWithdrawalLongTokenSwapPathCoverage_cancelWithdrawal(
195 | | address[] memory longTokenSwapPath
196 | | ) internal {
197 | * | if (longTokenSwapPath.length == 0) {
198 | * | fl.log("Withdrawal longTokenSwapPath is empty");
199 | | }
200 | * | if (longTokenSwapPath.length == 1) {
201 | | fl.log("Withdrawal longTokenSwapPath has 1 element");
202 | | }
203 | * | if (longTokenSwapPath.length == 2) {
204 | | fl.log("Withdrawal longTokenSwapPath has 2 elements");
205 | | }
206 | * | if (longTokenSwapPath.length >= 3) {
207 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements");
208 | | }
209 | | }
210 | |
211 | * | function _logWithdrawalShortTokenSwapPathCoverage_cancelWithdrawal(
212 | | address[] memory shortTokenSwapPath
213 | | ) internal {
214 | * | if (shortTokenSwapPath.length == 0) {
215 | * | fl.log("Withdrawal shortTokenSwapPath is empty");
216 | | }
217 | * | if (shortTokenSwapPath.length == 1) {
218 | | fl.log("Withdrawal shortTokenSwapPath has 1 element");
219 | | }
220 | * | if (shortTokenSwapPath.length == 2) {
221 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements");
222 | | }
223 | * | if (shortTokenSwapPath.length >= 3) {
224 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements");
225 | | }
226 | | }
227 | |
228 | * | function _logWithdrawalMarketTokenAmountCoverage_cancelWithdrawal(
229 | | uint256 marketTokenAmount
230 | | ) internal {
231 | * | if (marketTokenAmount == 0) {
232 | | fl.log("Withdrawal marketTokenAmount is 0");
233 | | }
234 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) {
235 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6");
236 | | }
237 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) {
238 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12");
239 | | }
240 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) {
241 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18");
242 | | }
243 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) {
244 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24");
245 | | }
246 | * | if (marketTokenAmount > 1e24) {
247 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24");
248 | | }
249 | | }
250 | |
251 | * | function _logWithdrawalMinLongTokenAmountCoverage_cancelWithdrawal(
252 | | uint256 minLongTokenAmount
253 | | ) internal {
254 | * | if (minLongTokenAmount == 0) {
255 | | fl.log("Withdrawal minLongTokenAmount is 0");
256 | | }
257 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) {
258 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6");
259 | | }
260 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) {
261 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12");
262 | | }
263 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) {
264 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18");
265 | | }
266 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) {
267 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24");
268 | | }
269 | * | if (minLongTokenAmount > 1e24) {
270 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24");
271 | | }
272 | | }
273 | |
274 | * | function _logWithdrawalMinShortTokenAmountCoverage_cancelWithdrawal(
275 | | uint256 minShortTokenAmount
276 | | ) internal {
277 | * | if (minShortTokenAmount == 0) {
278 | | fl.log("Withdrawal minShortTokenAmount is 0");
279 | | }
280 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) {
281 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6");
282 | | }
283 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) {
284 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12");
285 | | }
286 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) {
287 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18");
288 | | }
289 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) {
290 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24");
291 | | }
292 | * | if (minShortTokenAmount > 1e24) {
293 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24");
294 | | }
295 | | }
296 | |
297 | * | function _logWithdrawalUpdatedAtBlockCoverage_cancelWithdrawal(
298 | | uint256 updatedAtBlock
299 | | ) internal {
300 | * | if (updatedAtBlock == 0) {
301 | | fl.log("Withdrawal updatedAtBlock is 0");
302 | | } else {
303 | * | fl.log("Withdrawal updatedAtBlock is non-zero");
304 | | }
305 | | }
306 | |
307 | * | function _logWithdrawalUpdatedAtTimeCoverage_cancelWithdrawal(
308 | | uint256 updatedAtTime
309 | | ) internal {
310 | * | if (updatedAtTime == 0) {
311 | | fl.log("Withdrawal updatedAtTime is 0");
312 | | } else {
313 | * | fl.log("Withdrawal updatedAtTime is non-zero");
314 | | }
315 | | }
316 | |
317 | * | function _logWithdrawalExecutionFeeCoverage_cancelWithdrawal(
318 | | uint256 executionFee
319 | | ) internal {
320 | * | if (executionFee == 0) {
321 | * | fl.log("Withdrawal executionFee is 0");
322 | | }
323 | * | if (executionFee > 0 && executionFee <= 1e6) {
324 | | fl.log("Withdrawal executionFee is between 0 and 1e6");
325 | | }
326 | * | if (executionFee > 1e6 && executionFee <= 1e12) {
327 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12");
328 | | }
329 | * | if (executionFee > 1e12 && executionFee <= 1e18) {
330 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18");
331 | | }
332 | * | if (executionFee > 1e18 && executionFee <= 1e24) {
333 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24");
334 | | }
335 | * | if (executionFee > 1e24) {
336 | | fl.log("Withdrawal executionFee is greater than 1e24");
337 | | }
338 | | }
339 | |
340 | * | function _logWithdrawalCallbackGasLimitCoverage_cancelWithdrawal(
341 | | uint256 callbackGasLimit
342 | | ) internal {
343 | * | if (callbackGasLimit == 0) {
344 | | fl.log("Withdrawal callbackGasLimit is 0");
345 | | }
346 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
347 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6");
348 | | }
349 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
350 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12");
351 | | }
352 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
353 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18");
354 | | }
355 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
356 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24");
357 | | }
358 | * | if (callbackGasLimit > 1e24) {
359 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24");
360 | | }
361 | | }
362 | |
363 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage_cancelWithdrawal(
364 | | bool shouldUnwrapNativeToken
365 | | ) internal {
366 | * | if (shouldUnwrapNativeToken) {
367 | | fl.log("Withdrawal shouldUnwrapNativeToken is true");
368 | | } else {
369 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false");
370 | | }
371 | | }
372 | | }
373 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalCreatedCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract WithdrawalCreatedCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ CREATE WITHDRAWAL COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | * | function _checkCreateWithdrawalCoverage(
14 | | Withdrawal.Props memory withdrawalProps
15 | | ) internal {
16 | * | _logWithdrawalAccountCoverage(withdrawalProps.addresses.account);
17 | * | _logWithdrawalReceiverCoverage(withdrawalProps.addresses.receiver);
18 | * | _logWithdrawalCallbackContractCoverage(
19 | * | withdrawalProps.addresses.callbackContract
20 | | );
21 | * | _logWithdrawalUiFeeReceiverCoverage(
22 | * | withdrawalProps.addresses.uiFeeReceiver
23 | | );
24 | * | _logWithdrawalMarketCoverage(withdrawalProps.addresses.market);
25 | * | _logWithdrawalLongTokenSwapPathCoverage(
26 | * | withdrawalProps.addresses.longTokenSwapPath
27 | | );
28 | * | _logWithdrawalShortTokenSwapPathCoverage(
29 | * | withdrawalProps.addresses.shortTokenSwapPath
30 | | );
31 | * | _logWithdrawalMarketTokenAmountCoverage(
32 | * | withdrawalProps.numbers.marketTokenAmount
33 | | );
34 | * | _logWithdrawalMinLongTokenAmountCoverage(
35 | * | withdrawalProps.numbers.minLongTokenAmount
36 | | );
37 | * | _logWithdrawalMinShortTokenAmountCoverage(
38 | * | withdrawalProps.numbers.minShortTokenAmount
39 | | );
40 | * | _logWithdrawalUpdatedAtBlockCoverage(
41 | * | withdrawalProps.numbers.updatedAtBlock
42 | | );
43 | * | _logWithdrawalUpdatedAtTimeCoverage(
44 | * | withdrawalProps.numbers.updatedAtTime
45 | | );
46 | * | _logWithdrawalExecutionFeeCoverage(
47 | * | withdrawalProps.numbers.executionFee
48 | | );
49 | * | _logWithdrawalCallbackGasLimitCoverage(
50 | * | withdrawalProps.numbers.callbackGasLimit
51 | | );
52 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage(
53 | * | withdrawalProps.flags.shouldUnwrapNativeToken
54 | | );
55 | | }
56 | |
57 | * | function _logWithdrawalAccountCoverage(address account) internal {
58 | * | if (account == USER0) {
59 | * | fl.log("Withdrawal account USER0 hit");
60 | | }
61 | * | if (account == USER1) {
62 | | fl.log("Withdrawal account USER1 hit");
63 | | }
64 | * | if (account == USER2) {
65 | | fl.log("Withdrawal account USER2 hit");
66 | | }
67 | * | if (account == USER3) {
68 | | fl.log("Withdrawal account USER3 hit");
69 | | }
70 | * | if (account == USER4) {
71 | | fl.log("Withdrawal account USER4 hit");
72 | | }
73 | * | if (account == USER5) {
74 | | fl.log("Withdrawal account USER5 hit");
75 | | }
76 | * | if (account == USER6) {
77 | | fl.log("Withdrawal account USER6 hit");
78 | | }
79 | * | if (account == USER7) {
80 | | fl.log("Withdrawal account USER7 hit");
81 | | }
82 | * | if (account == USER8) {
83 | | fl.log("Withdrawal account USER8 hit");
84 | | }
85 | * | if (account == USER9) {
86 | | fl.log("Withdrawal account USER9 hit");
87 | | }
88 | * | if (account == USER10) {
89 | | fl.log("Withdrawal account USER10 hit");
90 | | }
91 | * | if (account == USER11) {
92 | | fl.log("Withdrawal account USER11 hit");
93 | | }
94 | * | if (account == USER12) {
95 | | fl.log("Withdrawal account USER12 hit");
96 | | }
97 | * | if (account == USER13) {
98 | | fl.log("Withdrawal account USER13 hit");
99 | | }
100 | | }
101 | |
102 | * | function _logWithdrawalReceiverCoverage(address receiver) internal {
103 | * | if (receiver == USER0) {
104 | * | fl.log("Withdrawal receiver USER0 hit");
105 | | }
106 | * | if (receiver == USER1) {
107 | | fl.log("Withdrawal receiver USER1 hit");
108 | | }
109 | * | if (receiver == USER2) {
110 | | fl.log("Withdrawal receiver USER2 hit");
111 | | }
112 | * | if (receiver == USER3) {
113 | | fl.log("Withdrawal receiver USER3 hit");
114 | | }
115 | * | if (receiver == USER4) {
116 | | fl.log("Withdrawal receiver USER4 hit");
117 | | }
118 | * | if (receiver == USER5) {
119 | | fl.log("Withdrawal receiver USER5 hit");
120 | | }
121 | * | if (receiver == USER6) {
122 | | fl.log("Withdrawal receiver USER6 hit");
123 | | }
124 | * | if (receiver == USER7) {
125 | | fl.log("Withdrawal receiver USER7 hit");
126 | | }
127 | * | if (receiver == USER8) {
128 | | fl.log("Withdrawal receiver USER8 hit");
129 | | }
130 | * | if (receiver == USER9) {
131 | | fl.log("Withdrawal receiver USER9 hit");
132 | | }
133 | * | if (receiver == USER10) {
134 | | fl.log("Withdrawal receiver USER10 hit");
135 | | }
136 | * | if (receiver == USER11) {
137 | | fl.log("Withdrawal receiver USER11 hit");
138 | | }
139 | * | if (receiver == USER12) {
140 | | fl.log("Withdrawal receiver USER12 hit");
141 | | }
142 | * | if (receiver == USER13) {
143 | | fl.log("Withdrawal receiver USER13 hit");
144 | | }
145 | | }
146 | * | function _logWithdrawalCallbackContractCoverage(
147 | | address callbackContract
148 | | ) internal {
149 | * | if (callbackContract == address(0)) {
150 | * | fl.log("Withdrawal callbackContract is address(0)");
151 | | } else {
152 | | fl.log("Withdrawal callbackContract is non-zero address");
153 | | }
154 | | }
155 | |
156 | * | function _logWithdrawalUiFeeReceiverCoverage(
157 | | address uiFeeReceiver
158 | | ) internal {
159 | * | if (uiFeeReceiver == address(0)) {
160 | * | fl.log("Withdrawal uiFeeReceiver is address(0)");
161 | | } else {
162 | | fl.log("Withdrawal uiFeeReceiver is non-zero address");
163 | | }
164 | | }
165 | |
166 | * | function _logWithdrawalMarketCoverage(address market) internal {
167 | * | if (market == address(market_0_WETH_USDC)) {
168 | * | fl.log("Withdrawal market market_0_WETH_USDC hit");
169 | | }
170 | |
171 | * | if (market == address(market_WBTC_WBTC_USDC)) {
172 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit");
173 | | }
174 | * | if (market == address(market_WETH_WETH_USDC)) {
175 | * | fl.log("Withdrawal market market_WETH_WETH_USDC hit");
176 | | }
177 | * | if (market == address(market_WETH_WETH_USDT)) {
178 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit");
179 | | }
180 | | }
181 | |
182 | * | function _logWithdrawalLongTokenSwapPathCoverage(
183 | | address[] memory longTokenSwapPath
184 | | ) internal {
185 | * | if (longTokenSwapPath.length == 0) {
186 | * | fl.log("Withdrawal longTokenSwapPath is empty");
187 | | }
188 | * | if (longTokenSwapPath.length == 1) {
189 | | fl.log("Withdrawal longTokenSwapPath has 1 element");
190 | | }
191 | * | if (longTokenSwapPath.length == 2) {
192 | | fl.log("Withdrawal longTokenSwapPath has 2 elements");
193 | | }
194 | * | if (longTokenSwapPath.length >= 3) {
195 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements");
196 | | }
197 | | }
198 | |
199 | * | function _logWithdrawalShortTokenSwapPathCoverage(
200 | | address[] memory shortTokenSwapPath
201 | | ) internal {
202 | * | if (shortTokenSwapPath.length == 0) {
203 | * | fl.log("Withdrawal shortTokenSwapPath is empty");
204 | | }
205 | * | if (shortTokenSwapPath.length == 1) {
206 | | fl.log("Withdrawal shortTokenSwapPath has 1 element");
207 | | }
208 | * | if (shortTokenSwapPath.length == 2) {
209 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements");
210 | | }
211 | * | if (shortTokenSwapPath.length >= 3) {
212 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements");
213 | | }
214 | | }
215 | |
216 | * | function _logWithdrawalMarketTokenAmountCoverage(
217 | | uint256 marketTokenAmount
218 | | ) internal {
219 | * | if (marketTokenAmount == 0) {
220 | | fl.log("Withdrawal marketTokenAmount is 0");
221 | | }
222 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) {
223 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6");
224 | | }
225 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) {
226 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12");
227 | | }
228 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) {
229 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18");
230 | | }
231 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) {
232 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24");
233 | | }
234 | * | if (marketTokenAmount > 1e24) {
235 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24");
236 | | }
237 | | }
238 | |
239 | * | function _logWithdrawalMinLongTokenAmountCoverage(
240 | | uint256 minLongTokenAmount
241 | | ) internal {
242 | * | if (minLongTokenAmount == 0) {
243 | | fl.log("Withdrawal minLongTokenAmount is 0");
244 | | }
245 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) {
246 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6");
247 | | }
248 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) {
249 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12");
250 | | }
251 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) {
252 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18");
253 | | }
254 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) {
255 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24");
256 | | }
257 | * | if (minLongTokenAmount > 1e24) {
258 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24");
259 | | }
260 | | }
261 | |
262 | * | function _logWithdrawalMinShortTokenAmountCoverage(
263 | | uint256 minShortTokenAmount
264 | | ) internal {
265 | * | if (minShortTokenAmount == 0) {
266 | | fl.log("Withdrawal minShortTokenAmount is 0");
267 | | }
268 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) {
269 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6");
270 | | }
271 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) {
272 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12");
273 | | }
274 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) {
275 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18");
276 | | }
277 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) {
278 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24");
279 | | }
280 | * | if (minShortTokenAmount > 1e24) {
281 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24");
282 | | }
283 | | }
284 | |
285 | * | function _logWithdrawalUpdatedAtBlockCoverage(
286 | | uint256 updatedAtBlock
287 | | ) internal {
288 | * | if (updatedAtBlock == 0) {
289 | | fl.log("Withdrawal updatedAtBlock is 0");
290 | | } else {
291 | * | fl.log("Withdrawal updatedAtBlock is non-zero");
292 | | }
293 | | }
294 | |
295 | * | function _logWithdrawalUpdatedAtTimeCoverage(
296 | | uint256 updatedAtTime
297 | | ) internal {
298 | * | if (updatedAtTime == 0) {
299 | | fl.log("Withdrawal updatedAtTime is 0");
300 | | } else {
301 | * | fl.log("Withdrawal updatedAtTime is non-zero");
302 | | }
303 | | }
304 | |
305 | * | function _logWithdrawalExecutionFeeCoverage(uint256 executionFee) internal {
306 | * | if (executionFee == 0) {
307 | * | fl.log("Withdrawal executionFee is 0");
308 | | }
309 | * | if (executionFee > 0 && executionFee <= 1e6) {
310 | | fl.log("Withdrawal executionFee is between 0 and 1e6");
311 | | }
312 | * | if (executionFee > 1e6 && executionFee <= 1e12) {
313 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12");
314 | | }
315 | * | if (executionFee > 1e12 && executionFee <= 1e18) {
316 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18");
317 | | }
318 | * | if (executionFee > 1e18 && executionFee <= 1e24) {
319 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24");
320 | | }
321 | * | if (executionFee > 1e24) {
322 | | fl.log("Withdrawal executionFee is greater than 1e24");
323 | | }
324 | | }
325 | |
326 | * | function _logWithdrawalCallbackGasLimitCoverage(
327 | | uint256 callbackGasLimit
328 | | ) internal {
329 | * | if (callbackGasLimit == 0) {
330 | | fl.log("Withdrawal callbackGasLimit is 0");
331 | | }
332 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
333 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6");
334 | | }
335 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
336 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12");
337 | | }
338 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
339 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18");
340 | | }
341 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
342 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24");
343 | | }
344 | * | if (callbackGasLimit > 1e24) {
345 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24");
346 | | }
347 | | }
348 | |
349 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage(
350 | | bool shouldUnwrapNativeToken
351 | | ) internal {
352 | * | if (shouldUnwrapNativeToken) {
353 | | fl.log("Withdrawal shouldUnwrapNativeToken is true");
354 | | } else {
355 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false");
356 | | }
357 | | }
358 | | }
359 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalExecuteAtomicCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract WithdrawalExecuteAtomicCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ EXECUTE ATOMIC WITHDRAWAL COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | * | function _checkExecuteAtomicWithdrawalCoverage(
13 | | Withdrawal.Props memory withdrawalProps
14 | | ) internal {
15 | * | _logWithdrawalAccountCoverage_executeAtomicWithdrawal(
16 | * | withdrawalProps.addresses.account
17 | | );
18 | * | _logWithdrawalReceiverCoverage_executeAtomicWithdrawal(
19 | * | withdrawalProps.addresses.receiver
20 | | );
21 | * | _logWithdrawalCallbackContractCoverage_executeAtomicWithdrawal(
22 | * | withdrawalProps.addresses.callbackContract
23 | | );
24 | * | _logWithdrawalUiFeeReceiverCoverage_executeAtomicWithdrawal(
25 | * | withdrawalProps.addresses.uiFeeReceiver
26 | | );
27 | * | _logWithdrawalMarketCoverage_executeAtomicWithdrawal(
28 | * | withdrawalProps.addresses.market
29 | | );
30 | * | _logWithdrawalLongTokenSwapPathCoverage_executeAtomicWithdrawal(
31 | * | withdrawalProps.addresses.longTokenSwapPath
32 | | );
33 | * | _logWithdrawalShortTokenSwapPathCoverage_executeAtomicWithdrawal(
34 | * | withdrawalProps.addresses.shortTokenSwapPath
35 | | );
36 | * | _logWithdrawalMarketTokenAmountCoverage_executeAtomicWithdrawal(
37 | * | withdrawalProps.numbers.marketTokenAmount
38 | | );
39 | * | _logWithdrawalMinLongTokenAmountCoverage_executeAtomicWithdrawal(
40 | * | withdrawalProps.numbers.minLongTokenAmount
41 | | );
42 | * | _logWithdrawalMinShortTokenAmountCoverage_executeAtomicWithdrawal(
43 | * | withdrawalProps.numbers.minShortTokenAmount
44 | | );
45 | * | _logWithdrawalUpdatedAtBlockCoverage_executeAtomicWithdrawal(
46 | * | withdrawalProps.numbers.updatedAtBlock
47 | | );
48 | * | _logWithdrawalUpdatedAtTimeCoverage_executeAtomicWithdrawal(
49 | * | withdrawalProps.numbers.updatedAtTime
50 | | );
51 | * | _logWithdrawalExecutionFeeCoverage_executeAtomicWithdrawal(
52 | * | withdrawalProps.numbers.executionFee
53 | | );
54 | * | _logWithdrawalCallbackGasLimitCoverage_executeAtomicWithdrawal(
55 | * | withdrawalProps.numbers.callbackGasLimit
56 | | );
57 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage_executeAtomicWithdrawal(
58 | * | withdrawalProps.flags.shouldUnwrapNativeToken
59 | | );
60 | | }
61 | |
62 | * | function _logWithdrawalAccountCoverage_executeAtomicWithdrawal(
63 | | address account
64 | | ) internal {
65 | * | if (account == USER0) {
66 | * | fl.log("Withdrawal account USER0 hit");
67 | | }
68 | * | if (account == USER1) {
69 | | fl.log("Withdrawal account USER1 hit");
70 | | }
71 | * | if (account == USER2) {
72 | | fl.log("Withdrawal account USER2 hit");
73 | | }
74 | * | if (account == USER3) {
75 | | fl.log("Withdrawal account USER3 hit");
76 | | }
77 | * | if (account == USER4) {
78 | | fl.log("Withdrawal account USER4 hit");
79 | | }
80 | * | if (account == USER5) {
81 | | fl.log("Withdrawal account USER5 hit");
82 | | }
83 | * | if (account == USER6) {
84 | | fl.log("Withdrawal account USER6 hit");
85 | | }
86 | * | if (account == USER7) {
87 | | fl.log("Withdrawal account USER7 hit");
88 | | }
89 | * | if (account == USER8) {
90 | | fl.log("Withdrawal account USER8 hit");
91 | | }
92 | * | if (account == USER9) {
93 | | fl.log("Withdrawal account USER9 hit");
94 | | }
95 | * | if (account == USER10) {
96 | | fl.log("Withdrawal account USER10 hit");
97 | | }
98 | * | if (account == USER11) {
99 | | fl.log("Withdrawal account USER11 hit");
100 | | }
101 | * | if (account == USER12) {
102 | | fl.log("Withdrawal account USER12 hit");
103 | | }
104 | * | if (account == USER13) {
105 | | fl.log("Withdrawal account USER13 hit");
106 | | }
107 | | }
108 | |
109 | * | function _logWithdrawalReceiverCoverage_executeAtomicWithdrawal(
110 | | address receiver
111 | | ) internal {
112 | * | if (receiver == USER0) {
113 | * | fl.log("Withdrawal receiver USER0 hit");
114 | | }
115 | * | if (receiver == USER1) {
116 | | fl.log("Withdrawal receiver USER1 hit");
117 | | }
118 | * | if (receiver == USER2) {
119 | | fl.log("Withdrawal receiver USER2 hit");
120 | | }
121 | * | if (receiver == USER3) {
122 | | fl.log("Withdrawal receiver USER3 hit");
123 | | }
124 | * | if (receiver == USER4) {
125 | | fl.log("Withdrawal receiver USER4 hit");
126 | | }
127 | * | if (receiver == USER5) {
128 | | fl.log("Withdrawal receiver USER5 hit");
129 | | }
130 | * | if (receiver == USER6) {
131 | | fl.log("Withdrawal receiver USER6 hit");
132 | | }
133 | * | if (receiver == USER7) {
134 | | fl.log("Withdrawal receiver USER7 hit");
135 | | }
136 | * | if (receiver == USER8) {
137 | | fl.log("Withdrawal receiver USER8 hit");
138 | | }
139 | * | if (receiver == USER9) {
140 | | fl.log("Withdrawal receiver USER9 hit");
141 | | }
142 | * | if (receiver == USER10) {
143 | | fl.log("Withdrawal receiver USER10 hit");
144 | | }
145 | * | if (receiver == USER11) {
146 | | fl.log("Withdrawal receiver USER11 hit");
147 | | }
148 | * | if (receiver == USER12) {
149 | | fl.log("Withdrawal receiver USER12 hit");
150 | | }
151 | * | if (receiver == USER13) {
152 | | fl.log("Withdrawal receiver USER13 hit");
153 | | }
154 | | }
155 | * | function _logWithdrawalCallbackContractCoverage_executeAtomicWithdrawal(
156 | | address callbackContract
157 | | ) internal {
158 | * | if (callbackContract == address(0)) {
159 | * | fl.log("Withdrawal callbackContract is address(0)");
160 | | } else {
161 | | fl.log("Withdrawal callbackContract is non-zero address");
162 | | }
163 | | }
164 | |
165 | * | function _logWithdrawalUiFeeReceiverCoverage_executeAtomicWithdrawal(
166 | | address uiFeeReceiver
167 | | ) internal {
168 | * | if (uiFeeReceiver == address(0)) {
169 | * | fl.log("Withdrawal uiFeeReceiver is address(0)");
170 | | } else {
171 | | fl.log("Withdrawal uiFeeReceiver is non-zero address");
172 | | }
173 | | }
174 | |
175 | * | function _logWithdrawalMarketCoverage_executeAtomicWithdrawal(
176 | | address market
177 | | ) internal {
178 | * | if (market == address(market_0_WETH_USDC)) {
179 | | fl.log("Withdrawal market market_0_WETH_USDC hit");
180 | | }
181 | |
182 | * | if (market == address(market_WBTC_WBTC_USDC)) {
183 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit");
184 | | }
185 | * | if (market == address(market_WETH_WETH_USDC)) {
186 | | fl.log("Withdrawal market market_WETH_WETH_USDC hit");
187 | | }
188 | * | if (market == address(market_WETH_WETH_USDT)) {
189 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit");
190 | | }
191 | | }
192 | |
193 | * | function _logWithdrawalLongTokenSwapPathCoverage_executeAtomicWithdrawal(
194 | | address[] memory longTokenSwapPath
195 | | ) internal {
196 | * | if (longTokenSwapPath.length == 0) {
197 | * | fl.log("Withdrawal longTokenSwapPath is empty");
198 | | }
199 | * | if (longTokenSwapPath.length == 1) {
200 | | fl.log("Withdrawal longTokenSwapPath has 1 element");
201 | | }
202 | * | if (longTokenSwapPath.length == 2) {
203 | | fl.log("Withdrawal longTokenSwapPath has 2 elements");
204 | | }
205 | * | if (longTokenSwapPath.length >= 3) {
206 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements");
207 | | }
208 | | }
209 | |
210 | * | function _logWithdrawalShortTokenSwapPathCoverage_executeAtomicWithdrawal(
211 | | address[] memory shortTokenSwapPath
212 | | ) internal {
213 | * | if (shortTokenSwapPath.length == 0) {
214 | * | fl.log("Withdrawal shortTokenSwapPath is empty");
215 | | }
216 | * | if (shortTokenSwapPath.length == 1) {
217 | | fl.log("Withdrawal shortTokenSwapPath has 1 element");
218 | | }
219 | * | if (shortTokenSwapPath.length == 2) {
220 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements");
221 | | }
222 | * | if (shortTokenSwapPath.length >= 3) {
223 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements");
224 | | }
225 | | }
226 | |
227 | * | function _logWithdrawalMarketTokenAmountCoverage_executeAtomicWithdrawal(
228 | | uint256 marketTokenAmount
229 | | ) internal {
230 | * | if (marketTokenAmount == 0) {
231 | | fl.log("Withdrawal marketTokenAmount is 0");
232 | | }
233 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) {
234 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6");
235 | | }
236 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) {
237 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12");
238 | | }
239 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) {
240 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18");
241 | | }
242 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) {
243 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24");
244 | | }
245 | * | if (marketTokenAmount > 1e24) {
246 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24");
247 | | }
248 | | }
249 | |
250 | * | function _logWithdrawalMinLongTokenAmountCoverage_executeAtomicWithdrawal(
251 | | uint256 minLongTokenAmount
252 | | ) internal {
253 | * | if (minLongTokenAmount == 0) {
254 | | fl.log("Withdrawal minLongTokenAmount is 0");
255 | | }
256 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) {
257 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6");
258 | | }
259 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) {
260 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12");
261 | | }
262 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) {
263 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18");
264 | | }
265 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) {
266 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24");
267 | | }
268 | * | if (minLongTokenAmount > 1e24) {
269 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24");
270 | | }
271 | | }
272 | |
273 | * | function _logWithdrawalMinShortTokenAmountCoverage_executeAtomicWithdrawal(
274 | | uint256 minShortTokenAmount
275 | | ) internal {
276 | * | if (minShortTokenAmount == 0) {
277 | | fl.log("Withdrawal minShortTokenAmount is 0");
278 | | }
279 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) {
280 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6");
281 | | }
282 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) {
283 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12");
284 | | }
285 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) {
286 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18");
287 | | }
288 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) {
289 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24");
290 | | }
291 | * | if (minShortTokenAmount > 1e24) {
292 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24");
293 | | }
294 | | }
295 | |
296 | * | function _logWithdrawalUpdatedAtBlockCoverage_executeAtomicWithdrawal(
297 | | uint256 updatedAtBlock
298 | | ) internal {
299 | * | if (updatedAtBlock == 0) {
300 | | fl.log("Withdrawal updatedAtBlock is 0");
301 | | } else {
302 | * | fl.log("Withdrawal updatedAtBlock is non-zero");
303 | | }
304 | | }
305 | |
306 | * | function _logWithdrawalUpdatedAtTimeCoverage_executeAtomicWithdrawal(
307 | | uint256 updatedAtTime
308 | | ) internal {
309 | * | if (updatedAtTime == 0) {
310 | | fl.log("Withdrawal updatedAtTime is 0");
311 | | } else {
312 | * | fl.log("Withdrawal updatedAtTime is non-zero");
313 | | }
314 | | }
315 | |
316 | * | function _logWithdrawalExecutionFeeCoverage_executeAtomicWithdrawal(
317 | | uint256 executionFee
318 | | ) internal {
319 | * | if (executionFee == 0) {
320 | * | fl.log("Withdrawal executionFee is 0");
321 | | }
322 | * | if (executionFee > 0 && executionFee <= 1e6) {
323 | | fl.log("Withdrawal executionFee is between 0 and 1e6");
324 | | }
325 | * | if (executionFee > 1e6 && executionFee <= 1e12) {
326 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12");
327 | | }
328 | * | if (executionFee > 1e12 && executionFee <= 1e18) {
329 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18");
330 | | }
331 | * | if (executionFee > 1e18 && executionFee <= 1e24) {
332 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24");
333 | | }
334 | * | if (executionFee > 1e24) {
335 | | fl.log("Withdrawal executionFee is greater than 1e24");
336 | | }
337 | | }
338 | |
339 | * | function _logWithdrawalCallbackGasLimitCoverage_executeAtomicWithdrawal(
340 | | uint256 callbackGasLimit
341 | | ) internal {
342 | * | if (callbackGasLimit == 0) {
343 | | fl.log("Withdrawal callbackGasLimit is 0");
344 | | }
345 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
346 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6");
347 | | }
348 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
349 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12");
350 | | }
351 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
352 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18");
353 | | }
354 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
355 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24");
356 | | }
357 | * | if (callbackGasLimit > 1e24) {
358 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24");
359 | | }
360 | | }
361 | |
362 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage_executeAtomicWithdrawal(
363 | | bool shouldUnwrapNativeToken
364 | | ) internal {
365 | * | if (shouldUnwrapNativeToken) {
366 | | fl.log("Withdrawal shouldUnwrapNativeToken is true");
367 | | } else {
368 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false");
369 | | }
370 | | }
371 | | }
372 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalExecuteCoverage.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../../properties/BeforeAfter.sol";
6 | |
7 | | contract WithdrawalExecuteCoverage is BeforeAfter {
8 | | // /\_/\ ___
9 | | // = o_o =_______ \ \ EXECUTE WITHDRAWAL COVERAGE
10 | | // __^ __( \.__) )
11 | | // (@)<_____>__(_____)____/
12 | |
13 | | function _checkExecuteWithdrawalCoverage(
14 | | Withdrawal.Props memory withdrawalProps
15 | | ) internal {
16 | | _logWithdrawalAccountCoverage_executeWithdrawal(
17 | | withdrawalProps.addresses.account
18 | | );
19 | | _logWithdrawalReceiverCoverage_executeWithdrawal(
20 | | withdrawalProps.addresses.receiver
21 | | );
22 | | _logWithdrawalCallbackContractCoverage_executeWithdrawal(
23 | | withdrawalProps.addresses.callbackContract
24 | | );
25 | | _logWithdrawalUiFeeReceiverCoverage_executeWithdrawal(
26 | | withdrawalProps.addresses.uiFeeReceiver
27 | | );
28 | | _logWithdrawalMarketCoverage_executeWithdrawal(
29 | | withdrawalProps.addresses.market
30 | | );
31 | | _logWithdrawalLongTokenSwapPathCoverage_executeWithdrawal(
32 | | withdrawalProps.addresses.longTokenSwapPath
33 | | );
34 | | _logWithdrawalShortTokenSwapPathCoverage_executeWithdrawal(
35 | | withdrawalProps.addresses.shortTokenSwapPath
36 | | );
37 | | _logWithdrawalMarketTokenAmountCoverage_executeWithdrawal(
38 | | withdrawalProps.numbers.marketTokenAmount
39 | | );
40 | | _logWithdrawalMinLongTokenAmountCoverage_executeWithdrawal(
41 | | withdrawalProps.numbers.minLongTokenAmount
42 | | );
43 | | _logWithdrawalMinShortTokenAmountCoverage_executeWithdrawal(
44 | | withdrawalProps.numbers.minShortTokenAmount
45 | | );
46 | | _logWithdrawalUpdatedAtBlockCoverage_executeWithdrawal(
47 | | withdrawalProps.numbers.updatedAtBlock
48 | | );
49 | | _logWithdrawalUpdatedAtTimeCoverage_executeWithdrawal(
50 | | withdrawalProps.numbers.updatedAtTime
51 | | );
52 | | _logWithdrawalExecutionFeeCoverage_executeWithdrawal(
53 | | withdrawalProps.numbers.executionFee
54 | | );
55 | | _logWithdrawalCallbackGasLimitCoverage_executeWithdrawal(
56 | | withdrawalProps.numbers.callbackGasLimit
57 | | );
58 | | _logWithdrawalShouldUnwrapNativeTokenCoverage_executeWithdrawal(
59 | | withdrawalProps.flags.shouldUnwrapNativeToken
60 | | );
61 | | }
62 | |
63 | | function _logWithdrawalAccountCoverage_executeWithdrawal(
64 | | address account
65 | | ) internal {
66 | | if (account == USER0) {
67 | | fl.log("Withdrawal account USER0 hit");
68 | | }
69 | | if (account == USER1) {
70 | | fl.log("Withdrawal account USER1 hit");
71 | | }
72 | | if (account == USER2) {
73 | | fl.log("Withdrawal account USER2 hit");
74 | | }
75 | | if (account == USER3) {
76 | | fl.log("Withdrawal account USER3 hit");
77 | | }
78 | | if (account == USER4) {
79 | | fl.log("Withdrawal account USER4 hit");
80 | | }
81 | | if (account == USER5) {
82 | | fl.log("Withdrawal account USER5 hit");
83 | | }
84 | | if (account == USER6) {
85 | | fl.log("Withdrawal account USER6 hit");
86 | | }
87 | | if (account == USER7) {
88 | | fl.log("Withdrawal account USER7 hit");
89 | | }
90 | | if (account == USER8) {
91 | | fl.log("Withdrawal account USER8 hit");
92 | | }
93 | | if (account == USER9) {
94 | | fl.log("Withdrawal account USER9 hit");
95 | | }
96 | | if (account == USER10) {
97 | | fl.log("Withdrawal account USER10 hit");
98 | | }
99 | | if (account == USER11) {
100 | | fl.log("Withdrawal account USER11 hit");
101 | | }
102 | | if (account == USER12) {
103 | | fl.log("Withdrawal account USER12 hit");
104 | | }
105 | | if (account == USER13) {
106 | | fl.log("Withdrawal account USER13 hit");
107 | | }
108 | | }
109 | |
110 | | function _logWithdrawalReceiverCoverage_executeWithdrawal(
111 | | address receiver
112 | | ) internal {
113 | | if (receiver == USER0) {
114 | | fl.log("Withdrawal receiver USER0 hit");
115 | | }
116 | | if (receiver == USER1) {
117 | | fl.log("Withdrawal receiver USER1 hit");
118 | | }
119 | | if (receiver == USER2) {
120 | | fl.log("Withdrawal receiver USER2 hit");
121 | | }
122 | | if (receiver == USER3) {
123 | | fl.log("Withdrawal receiver USER3 hit");
124 | | }
125 | | if (receiver == USER4) {
126 | | fl.log("Withdrawal receiver USER4 hit");
127 | | }
128 | | if (receiver == USER5) {
129 | | fl.log("Withdrawal receiver USER5 hit");
130 | | }
131 | | if (receiver == USER6) {
132 | | fl.log("Withdrawal receiver USER6 hit");
133 | | }
134 | | if (receiver == USER7) {
135 | | fl.log("Withdrawal receiver USER7 hit");
136 | | }
137 | | if (receiver == USER8) {
138 | | fl.log("Withdrawal receiver USER8 hit");
139 | | }
140 | | if (receiver == USER9) {
141 | | fl.log("Withdrawal receiver USER9 hit");
142 | | }
143 | | if (receiver == USER10) {
144 | | fl.log("Withdrawal receiver USER10 hit");
145 | | }
146 | | if (receiver == USER11) {
147 | | fl.log("Withdrawal receiver USER11 hit");
148 | | }
149 | | if (receiver == USER12) {
150 | | fl.log("Withdrawal receiver USER12 hit");
151 | | }
152 | | if (receiver == USER13) {
153 | | fl.log("Withdrawal receiver USER13 hit");
154 | | }
155 | | }
156 | | function _logWithdrawalCallbackContractCoverage_executeWithdrawal(
157 | | address callbackContract
158 | | ) internal {
159 | | if (callbackContract == address(0)) {
160 | | fl.log("Withdrawal callbackContract is address(0)");
161 | | } else {
162 | | fl.log("Withdrawal callbackContract is non-zero address");
163 | | }
164 | | }
165 | |
166 | | function _logWithdrawalUiFeeReceiverCoverage_executeWithdrawal(
167 | | address uiFeeReceiver
168 | | ) internal {
169 | | if (uiFeeReceiver == address(0)) {
170 | | fl.log("Withdrawal uiFeeReceiver is address(0)");
171 | | } else {
172 | | fl.log("Withdrawal uiFeeReceiver is non-zero address");
173 | | }
174 | | }
175 | |
176 | | function _logWithdrawalMarketCoverage_executeWithdrawal(
177 | | address market
178 | | ) internal {
179 | | if (market == address(market_0_WETH_USDC)) {
180 | | fl.log("Withdrawal market market_0_WETH_USDC hit");
181 | | }
182 | |
183 | | if (market == address(market_WBTC_WBTC_USDC)) {
184 | | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit");
185 | | }
186 | | if (market == address(market_WETH_WETH_USDC)) {
187 | | fl.log("Withdrawal market market_WETH_WETH_USDC hit");
188 | | }
189 | | if (market == address(market_WETH_WETH_USDT)) {
190 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit");
191 | | }
192 | | }
193 | |
194 | | function _logWithdrawalLongTokenSwapPathCoverage_executeWithdrawal(
195 | | address[] memory longTokenSwapPath
196 | | ) internal {
197 | | if (longTokenSwapPath.length == 0) {
198 | | fl.log("Withdrawal longTokenSwapPath is empty");
199 | | }
200 | | if (longTokenSwapPath.length == 1) {
201 | | fl.log("Withdrawal longTokenSwapPath has 1 element");
202 | | }
203 | | if (longTokenSwapPath.length == 2) {
204 | | fl.log("Withdrawal longTokenSwapPath has 2 elements");
205 | | }
206 | | if (longTokenSwapPath.length >= 3) {
207 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements");
208 | | }
209 | | }
210 | |
211 | | function _logWithdrawalShortTokenSwapPathCoverage_executeWithdrawal(
212 | | address[] memory shortTokenSwapPath
213 | | ) internal {
214 | | if (shortTokenSwapPath.length == 0) {
215 | | fl.log("Withdrawal shortTokenSwapPath is empty");
216 | | }
217 | | if (shortTokenSwapPath.length == 1) {
218 | | fl.log("Withdrawal shortTokenSwapPath has 1 element");
219 | | }
220 | | if (shortTokenSwapPath.length == 2) {
221 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements");
222 | | }
223 | | if (shortTokenSwapPath.length >= 3) {
224 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements");
225 | | }
226 | | }
227 | |
228 | | function _logWithdrawalMarketTokenAmountCoverage_executeWithdrawal(
229 | | uint256 marketTokenAmount
230 | | ) internal {
231 | | if (marketTokenAmount == 0) {
232 | | fl.log("Withdrawal marketTokenAmount is 0");
233 | | }
234 | | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) {
235 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6");
236 | | }
237 | | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) {
238 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12");
239 | | }
240 | | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) {
241 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18");
242 | | }
243 | | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) {
244 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24");
245 | | }
246 | | if (marketTokenAmount > 1e24) {
247 | | fl.log("Withdrawal marketTokenAmount is greater than 1e24");
248 | | }
249 | | }
250 | |
251 | | function _logWithdrawalMinLongTokenAmountCoverage_executeWithdrawal(
252 | | uint256 minLongTokenAmount
253 | | ) internal {
254 | | if (minLongTokenAmount == 0) {
255 | | fl.log("Withdrawal minLongTokenAmount is 0");
256 | | }
257 | | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) {
258 | | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6");
259 | | }
260 | | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) {
261 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12");
262 | | }
263 | | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) {
264 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18");
265 | | }
266 | | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) {
267 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24");
268 | | }
269 | | if (minLongTokenAmount > 1e24) {
270 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24");
271 | | }
272 | | }
273 | |
274 | | function _logWithdrawalMinShortTokenAmountCoverage_executeWithdrawal(
275 | | uint256 minShortTokenAmount
276 | | ) internal {
277 | | if (minShortTokenAmount == 0) {
278 | | fl.log("Withdrawal minShortTokenAmount is 0");
279 | | }
280 | | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) {
281 | | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6");
282 | | }
283 | | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) {
284 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12");
285 | | }
286 | | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) {
287 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18");
288 | | }
289 | | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) {
290 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24");
291 | | }
292 | | if (minShortTokenAmount > 1e24) {
293 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24");
294 | | }
295 | | }
296 | |
297 | | function _logWithdrawalUpdatedAtBlockCoverage_executeWithdrawal(
298 | | uint256 updatedAtBlock
299 | | ) internal {
300 | | if (updatedAtBlock == 0) {
301 | | fl.log("Withdrawal updatedAtBlock is 0");
302 | | } else {
303 | | fl.log("Withdrawal updatedAtBlock is non-zero");
304 | | }
305 | | }
306 | |
307 | | function _logWithdrawalUpdatedAtTimeCoverage_executeWithdrawal(
308 | | uint256 updatedAtTime
309 | | ) internal {
310 | | if (updatedAtTime == 0) {
311 | | fl.log("Withdrawal updatedAtTime is 0");
312 | | } else {
313 | | fl.log("Withdrawal updatedAtTime is non-zero");
314 | | }
315 | | }
316 | |
317 | | function _logWithdrawalExecutionFeeCoverage_executeWithdrawal(
318 | | uint256 executionFee
319 | | ) internal {
320 | | if (executionFee == 0) {
321 | | fl.log("Withdrawal executionFee is 0");
322 | | }
323 | | if (executionFee > 0 && executionFee <= 1e6) {
324 | | fl.log("Withdrawal executionFee is between 0 and 1e6");
325 | | }
326 | | if (executionFee > 1e6 && executionFee <= 1e12) {
327 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12");
328 | | }
329 | | if (executionFee > 1e12 && executionFee <= 1e18) {
330 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18");
331 | | }
332 | | if (executionFee > 1e18 && executionFee <= 1e24) {
333 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24");
334 | | }
335 | | if (executionFee > 1e24) {
336 | | fl.log("Withdrawal executionFee is greater than 1e24");
337 | | }
338 | | }
339 | |
340 | | function _logWithdrawalCallbackGasLimitCoverage_executeWithdrawal(
341 | | uint256 callbackGasLimit
342 | | ) internal {
343 | | if (callbackGasLimit == 0) {
344 | | fl.log("Withdrawal callbackGasLimit is 0");
345 | | }
346 | | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) {
347 | | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6");
348 | | }
349 | | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) {
350 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12");
351 | | }
352 | | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) {
353 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18");
354 | | }
355 | | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) {
356 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24");
357 | | }
358 | | if (callbackGasLimit > 1e24) {
359 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24");
360 | | }
361 | | }
362 | |
363 | | function _logWithdrawalShouldUnwrapNativeTokenCoverage_executeWithdrawal(
364 | | bool shouldUnwrapNativeToken
365 | | ) internal {
366 | | if (shouldUnwrapNativeToken) {
367 | | fl.log("Withdrawal shouldUnwrapNativeToken is true");
368 | | } else {
369 | | fl.log("Withdrawal shouldUnwrapNativeToken is false");
370 | | }
371 | | }
372 | | }
373 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/ChainlinkMock.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "../../contracts/oracle/IOracleProvider.sol";
5 | |
6 | * | contract ChainlinkMock is IOracleProvider {
7 | | event TokenPriceSet(address token, uint min, uint max);
8 | |
9 | | struct TokenPrice {
10 | | uint min;
11 | | uint max;
12 | | }
13 | |
14 | | mapping(address => TokenPrice) private tokenPrices;
15 | |
16 | * | function setOraclePrice(address token, uint min, uint max, uint precisions) public {
17 | * | uint minPrice = min * (10 ** precisions);
18 | * | uint maxPrice = max * (10 ** precisions);
19 | * | tokenPrices[token] = TokenPrice(minPrice, maxPrice);
20 | * | emit TokenPriceSet(token, minPrice, maxPrice);
21 | | }
22 | * | function getOraclePrice(
23 | | address token,
24 | | bytes memory data
25 | * | ) external view returns (OracleUtils.ValidatedPrice memory) {
26 | * | TokenPrice memory tokenPrice = tokenPrices[token];
27 | |
28 | * | return
29 | * | OracleUtils.ValidatedPrice({
30 | * | token: token,
31 | * | min: tokenPrice.min,
32 | * | max: tokenPrice.max,
33 | * | timestamp: block.timestamp,
34 | * | provider: address(this)
35 | | });
36 | | }
37 | | }
38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/MockDEX.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.13;
4 | |
5 | | import {MockLP} from "./MockLP.sol";
6 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7 | |
8 | * | contract MockDex {
9 | | bool DEBUG = true;
10 | |
11 | | mapping(address => mapping(address => address)) public getPair;
12 | |
13 | | event PairCreated(address tokenA, address tokenB, address pair);
14 | | event LiquidityAdded(
15 | | address sender,
16 | | address tokenA,
17 | | address tokenB,
18 | | uint256 amountA,
19 | | uint256 amountB,
20 | | uint256 liquidity
21 | | );
22 | | event LiquidityRemoved(
23 | | address sender,
24 | | address tokenA,
25 | | address tokenB,
26 | | uint256 amountA,
27 | | uint256 amountB,
28 | | uint256 liquidity
29 | | );
30 | | event Swap(
31 | | address sender,
32 | | address tokenIn,
33 | | address tokenOut,
34 | | uint256 amountIn,
35 | | uint256 amountOut
36 | | );
37 | |
38 | * | function getTokenTransferProxy() public view returns (address) {
39 | * | return address(this);
40 | | }
41 | |
42 | * | function createPair(
43 | | address tokenA,
44 | | address tokenB,
45 | | uint256 feePercentage,
46 | | uint256 maxSwapPercentage,
47 | | string memory name,
48 | | string memory symbol
49 | * | ) public returns (address pair) {
50 | * | require(tokenA != tokenB, "DEX: IDENTICAL_ADDRESSES");
51 | * | require(getPair[tokenA][tokenB] == address(0), "DEX: PAIR_EXISTS");
52 | |
53 | | pair = address(
54 | | new MockLP(
55 | | IERC20(tokenA),
56 | | IERC20(tokenB),
57 | | feePercentage,
58 | | maxSwapPercentage,
59 | | name,
60 | | symbol
61 | | )
62 | | );
63 | |
64 | | getPair[tokenA][tokenB] = pair;
65 | | getPair[tokenB][tokenA] = pair;
66 | |
67 | | IERC20(tokenA).approve(pair, type(uint256).max);
68 | | IERC20(tokenB).approve(pair, type(uint256).max);
69 | |
70 | | emit PairCreated(tokenA, tokenB, pair);
71 | | }
72 | |
73 | | function addLiquidity(
74 | | address tokenA,
75 | | address tokenB,
76 | | uint256 amountADesired,
77 | | uint256 amountBDesired,
78 | | uint256 amountAMin,
79 | | uint256 amountBMin
80 | | ) public {
81 | | address pair = getPair[tokenA][tokenB];
82 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST");
83 | |
84 | | IERC20(tokenA).transferFrom(msg.sender, address(this), amountADesired);
85 | | IERC20(tokenB).transferFrom(msg.sender, address(this), amountBDesired);
86 | |
87 | | (uint256 amountA, uint256 amountB, uint256 liquidity) = MockLP(pair)
88 | | .addLiquidity(amountADesired, amountBDesired, amountAMin);
89 | |
90 | | IERC20(tokenA).transfer(msg.sender, amountADesired - amountA);
91 | | IERC20(tokenB).transfer(msg.sender, amountBDesired - amountB);
92 | | IERC20(pair).transfer(msg.sender, liquidity);
93 | |
94 | | emit LiquidityAdded(
95 | | msg.sender,
96 | | tokenA,
97 | | tokenB,
98 | | amountA,
99 | | amountB,
100 | | liquidity
101 | | );
102 | | }
103 | |
104 | | function removeLiquidity(
105 | | address tokenA,
106 | | address tokenB,
107 | | uint256 liquidity,
108 | | uint256 amountAMin,
109 | | uint256 amountBMin
110 | | ) public {
111 | | address pair = getPair[tokenA][tokenB];
112 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST");
113 | |
114 | | IERC20(pair).transferFrom(msg.sender, address(this), liquidity);
115 | |
116 | | (uint256 amountA, uint256 amountB) = MockLP(pair).removeLiquidity(
117 | | liquidity,
118 | | amountAMin,
119 | | amountBMin
120 | | );
121 | |
122 | | IERC20(tokenA).transfer(msg.sender, amountA);
123 | | IERC20(tokenB).transfer(msg.sender, amountB);
124 | |
125 | | emit LiquidityRemoved(
126 | | msg.sender,
127 | | tokenA,
128 | | tokenB,
129 | | amountA,
130 | | amountB,
131 | | liquidity
132 | | );
133 | | }
134 | |
135 | * | function swapExactTokensForTokens(
136 | | address tokenIn,
137 | | address tokenOut,
138 | | uint256 amountIn,
139 | | uint256 amountOutMin
140 | * | ) public {
141 | * | address pair = getPair[tokenIn][tokenOut];
142 | * | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST");
143 | |
144 | * | IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
145 | |
146 | * | uint256 amountOut = MockLP(pair).swapExactTokensForTokens(
147 | * | IERC20(tokenIn),
148 | * | IERC20(tokenOut),
149 | * | amountIn,
150 | * | amountOutMin
151 | | );
152 | |
153 | * | IERC20(tokenOut).transfer(msg.sender, amountOut);
154 | |
155 | * | emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut);
156 | | }
157 | |
158 | | function swapTokensForExactTokens(
159 | | address tokenIn,
160 | | address tokenOut,
161 | | uint256 amountInMax,
162 | | uint256 amountOut
163 | | ) public {
164 | | address pair = getPair[tokenIn][tokenOut];
165 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST");
166 | |
167 | | IERC20(tokenIn).transferFrom(msg.sender, address(this), amountInMax);
168 | |
169 | | uint256 amountIn = MockLP(pair).swapTokensForExactTokens(
170 | | IERC20(tokenIn),
171 | | IERC20(tokenOut),
172 | | amountInMax,
173 | | amountOut
174 | | );
175 | |
176 | | IERC20(tokenOut).transfer(msg.sender, amountOut);
177 | | IERC20(tokenIn).transfer(msg.sender, amountInMax - amountIn);
178 | |
179 | | emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut);
180 | | }
181 | | }
182 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/MockLP.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.13;
4 | |
5 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6 | | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
7 | | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8 | | import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
9 | |
10 | * | contract MockLP is ERC20 {
11 | | using SafeERC20 for IERC20;
12 | |
13 | | uint256 public feePercentage;
14 | | uint256 public maxSwapPercentage;
15 | |
16 | | IERC20 public tokenA;
17 | | IERC20 public tokenB;
18 | |
19 | | event Mint(
20 | | address sender,
21 | | uint256 amountA,
22 | | uint256 amountB,
23 | | uint256 liquidity
24 | | );
25 | | event Burn(
26 | | address sender,
27 | | uint256 amountA,
28 | | uint256 amountB,
29 | | uint256 liquidity
30 | | );
31 | |
32 | | constructor(
33 | | IERC20 _tokenA,
34 | | IERC20 _tokenB,
35 | | uint256 _feePercentage,
36 | | uint256 _maxSwapPercentage,
37 | | string memory name,
38 | | string memory symbol
39 | | ) ERC20(name, symbol) {
40 | | tokenA = _tokenA;
41 | | tokenB = _tokenB;
42 | | feePercentage = _feePercentage;
43 | | maxSwapPercentage = _maxSwapPercentage;
44 | | }
45 | |
46 | | function addLiquidity(
47 | | uint256 amountADesired,
48 | | uint256 amountBDesired,
49 | | uint256 minLiquidity
50 | | ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity) {
51 | | if (totalSupply() == 0) {
52 | | amountA = amountADesired;
53 | | amountB = amountBDesired;
54 | | liquidity = Math.sqrt(amountA * amountB);
55 | | } else {
56 | | uint256 reserveA = tokenA.balanceOf(address(this));
57 | | uint256 reserveB = tokenB.balanceOf(address(this));
58 | |
59 | | amountA = amountADesired;
60 | | amountB = (amountADesired * reserveB) / reserveA;
61 | |
62 | | if (amountB > amountBDesired) {
63 | | amountB = amountBDesired;
64 | | amountA = (amountB * reserveA) / reserveB;
65 | | }
66 | |
67 | | liquidity = (amountA * totalSupply()) / reserveA;
68 | | }
69 | |
70 | | require(liquidity >= minLiquidity, "Insufficient liquidity");
71 | |
72 | | tokenA.safeTransferFrom(msg.sender, address(this), amountA);
73 | | tokenB.safeTransferFrom(msg.sender, address(this), amountB);
74 | |
75 | | _mint(msg.sender, liquidity);
76 | |
77 | | emit Mint(msg.sender, amountA, amountB, liquidity);
78 | | }
79 | |
80 | | function removeLiquidity(
81 | | uint256 liquidity,
82 | | uint256 minAmountA,
83 | | uint256 minAmountB
84 | | ) external returns (uint256 amountA, uint256 amountB) {
85 | | uint256 reserveA = tokenA.balanceOf(address(this));
86 | | uint256 reserveB = tokenB.balanceOf(address(this));
87 | |
88 | | amountA = (liquidity * reserveA) / totalSupply();
89 | | amountB = (liquidity * reserveB) / totalSupply();
90 | |
91 | | require(amountA >= minAmountA, "Insufficient amountA");
92 | | require(amountB >= minAmountB, "Insufficient amountB");
93 | |
94 | | _burn(msg.sender, liquidity);
95 | |
96 | | tokenA.safeTransfer(msg.sender, amountA);
97 | | tokenB.safeTransfer(msg.sender, amountB);
98 | |
99 | | emit Burn(msg.sender, amountA, amountB, liquidity);
100 | | }
101 | |
102 | * | function swapExactTokensForTokens(
103 | | IERC20 tokenIn,
104 | | IERC20 tokenOut,
105 | | uint256 amountIn,
106 | | uint256 amountOutMin
107 | * | ) external returns (uint256 amountOut) {
108 | * | uint256 reserveIn = tokenIn.balanceOf(address(this));
109 | * | uint256 reserveOut = tokenOut.balanceOf(address(this));
110 | |
111 | * | require(
112 | * | amountIn <= (reserveIn * maxSwapPercentage) / 100,
113 | | "Exceeds max swap percentage"
114 | | );
115 | |
116 | * | uint256 amountInWithFee = (amountIn * (100 - feePercentage)) / 100;
117 | |
118 | * | amountOut = (amountInWithFee * reserveOut) / reserveIn;
119 | |
120 | * | require(amountOut >= amountOutMin, "Insufficient output amount");
121 | |
122 | * | tokenIn.safeTransferFrom(msg.sender, address(this), amountIn);
123 | * | tokenOut.safeTransfer(msg.sender, amountOut);
124 | | }
125 | |
126 | | function swapTokensForExactTokens(
127 | | IERC20 tokenIn,
128 | | IERC20 tokenOut,
129 | | uint256 amountInMax,
130 | | uint256 amountOut
131 | | ) external returns (uint256 amountIn) {
132 | | uint256 reserveIn = tokenIn.balanceOf(address(this));
133 | | uint256 reserveOut = tokenOut.balanceOf(address(this));
134 | |
135 | | require(
136 | | amountOut <= (reserveOut * maxSwapPercentage) / 100,
137 | | "Exceeds max swap percentage"
138 | | );
139 | |
140 | | amountIn = (amountOut * reserveIn) / reserveOut;
141 | |
142 | | amountIn = (amountIn * 100) / (100 - feePercentage);
143 | |
144 | | require(amountIn <= amountInMax, "Excessive input amount");
145 | |
146 | | tokenIn.safeTransferFrom(msg.sender, address(this), amountIn);
147 | | tokenOut.safeTransfer(msg.sender, amountOut);
148 | | }
149 | | }
150 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/ADLProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../logicalCoverage/ADLCoverage.sol";
6 | |
7 | | contract ADLProperties is ADLCoverage {
8 | * | function invariantPositionSizeUSDShouldDecrease(
9 | | uint positionSizeBefore,
10 | | uint positionSizeAfter,
11 | | uint reducedByDelta
12 | | ) internal {
13 | * | fl.eq(
14 | * | positionSizeBefore,
15 | * | positionSizeAfter + reducedByDelta,
16 | | "ADL-01 Position size shoud be reduced exactly by delta"
17 | | );
18 | | }
19 | | }
20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/BeforeAfter.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | | import "../helpers/BaseSetup.sol";
4 | |
5 | | contract BeforeAfter is BaseSetup {
6 | | error IncorrectShiftStateParams(
7 | | uint8 userIndex,
8 | | uint8 marketFromIndex,
9 | | uint8 marketToIndex,
10 | | address user,
11 | | address marketFrom,
12 | | address marketTo
13 | | );
14 | |
15 | * | function _gammaBefore() internal {
16 | * | _snapGammaState(0);
17 | | }
18 | * | function _gammaAfter() internal {
19 | * | _snapGammaState(1);
20 | | }
21 | |
22 | * | function _snapGammaState(uint8 callNum) internal {
23 | * | _captureVaultState(callNum);
24 | * | _collectDepositInfo(callNum);
25 | | }
26 | |
27 | * | function _positionBefore() internal {
28 | * | _snapPositionState(0);
29 | | }
30 | | function _positionAfter() internal {
31 | | _snapPositionState(1);
32 | | }
33 | * | function _collectDepositInfo(uint8 stateIndex) internal {
34 | * | State storage state = states[stateIndex];
35 | |
36 | * | for (uint i = 0; i < VAULTS.length; i++) {
37 | * | address vault = VAULTS[i];
38 | |
39 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault];
40 | |
41 | * | vaultInfo.totalAmount = 0;
42 | * | vaultInfo.totalSharesCalculated = 0;
43 | * | vaultInfo.oldestDepositTimestamp = type(uint256).max;
44 | * | vaultInfo.newestDepositTimestamp = 0;
45 | * | vaultInfo.collateralAmount = 0;
46 | |
47 | | //get collateral balance
48 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
49 | * | ReaderUtils.PositionInfo memory positionInfo;
50 | * | try
51 | * | reader.getPositionInfo(
52 | * | dataStore,
53 | * | referralStorage,
54 | * | PerpetualVault(vault).curPositionKey(),
55 | * | _getMarketPrices(
56 | * | vaultToMarket[vault],
57 | * | _setTokenPrices(5000e4)
58 | | ), //any price, checking for collateral
59 | * | uint256(0),
60 | * | address(0),
61 | * | true
62 | | )
63 | * | returns (ReaderUtils.PositionInfo memory return_positionInfo) {
64 | * | positionInfo = return_positionInfo;
65 | | } catch {
66 | | // Handle the error
67 | | }
68 | * | vaultInfo.collateralAmount = positionInfo
69 | | .position
70 | | .numbers
71 | | .collateralAmount;
72 | | }
73 | |
74 | * | if (vaultInfo.totalShares > 0) {
75 | * | vaultInfo.shareValue =
76 | * | ((vaultInfo.vaultUSDCBalance + vaultInfo.collateralAmount) *
77 | * | 1e30) /
78 | * | vaultInfo.totalShares;
79 | | } else {
80 | * | vaultInfo.shareValue = 0;
81 | | }
82 | |
83 | * | for (uint j = 0; j < USERS.length; j++) {
84 | * | address user = USERS[j];
85 | |
86 | * | UserState storage userState = vaultInfo.userStates[user];
87 | * | userState.USDCBalance = USDC.balanceOf(USERS[j]);
88 | |
89 | * | uint256[] memory depositIds = PerpetualVault(vault)
90 | * | .getUserDeposits(user);
91 | * | userState.depositIds = depositIds;
92 | * | userState.totalAmount = 0;
93 | * | userState.totalShares = 0;
94 | * | userState.lastDepositTimestamp = 0;
95 | |
96 | * | for (uint k = 0; k < depositIds.length; k++) {
97 | * | uint256 depositId = depositIds[k];
98 | * | DepositInfo memory deposit;
99 | * | (
100 | * | deposit.amount,
101 | * | deposit.shares, //aaded execution fee
102 | | ,
103 | | ,
104 | * | deposit.timestamp,
105 | |
106 | * | ) = PerpetualVault(vault).depositInfo(depositId);
107 | * | userState.deposits[depositId] = deposit.amount;
108 | |
109 | * | userState.totalAmount += deposit.amount;
110 | * | userState.totalShares += deposit.shares;
111 | |
112 | * | if (deposit.timestamp > userState.lastDepositTimestamp) {
113 | * | userState.lastDepositTimestamp = deposit.timestamp;
114 | | }
115 | |
116 | * | vaultInfo.totalAmount += deposit.amount;
117 | * | vaultInfo.totalSharesCalculated += deposit.shares;
118 | |
119 | * | if (deposit.timestamp < vaultInfo.oldestDepositTimestamp) {
120 | * | vaultInfo.oldestDepositTimestamp = deposit.timestamp;
121 | | }
122 | * | if (deposit.timestamp > vaultInfo.newestDepositTimestamp) {
123 | * | vaultInfo.newestDepositTimestamp = deposit.timestamp;
124 | | }
125 | | }
126 | * | if (userState.totalShares > 0) {
127 | * | userState.shareValue =
128 | * | (userState.totalShares * vaultInfo.shareValue) /
129 | * | 1e30;
130 | | } else {
131 | * | userState.shareValue = 0;
132 | | }
133 | | }
134 | | }
135 | * | if (DEBUG) {
136 | | // _analyzeDepositDistribution(stateIndex);
137 | | }
138 | | }
139 | |
140 | | function _analyzeDepositDistribution(uint8 stateIndex) internal view {
141 | | State storage state = states[stateIndex];
142 | |
143 | | for (uint i = 0; i < VAULTS.length; i++) {
144 | | address vault = VAULTS[i];
145 | | VaultInfo storage vaultInfo = state.vaultInfos[vault];
146 | |
147 | | for (uint j = 0; j < USERS.length; j++) {
148 | | address user = USERS[j];
149 | | UserState storage userState = vaultInfo.userStates[user];
150 | | uint256 userSharePercentage;
151 | | uint256 userAmountPercentage;
152 | | if (
153 | | vaultInfo.totalSharesCalculated != 0 &&
154 | | vaultInfo.totalAmount != 0
155 | | ) {
156 | | userSharePercentage =
157 | | (userState.totalShares * 1e18) /
158 | | vaultInfo.totalSharesCalculated;
159 | | userAmountPercentage =
160 | | (userState.totalAmount * 1e18) /
161 | | vaultInfo.totalAmount;
162 | | }
163 | | }
164 | | }
165 | | }
166 | |
167 | * | function _captureVaultState(uint8 stateIndex) internal {
168 | * | State storage state = states[stateIndex];
169 | |
170 | * | for (uint i = 0; i < VAULTS.length; i++) {
171 | * | address vault = VAULTS[i];
172 | * | PerpetualVault perpVault = PerpetualVault(vault);
173 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault];
174 | |
175 | * | vaultInfo.totalShares = perpVault.totalShares();
176 | * | vaultInfo.counter = perpVault.counter();
177 | * | vaultInfo.curPositionKey = perpVault.curPositionKey();
178 | * | vaultInfo.totalDepositAmount = perpVault.totalDepositAmount();
179 | * | vaultInfo.beenLong = perpVault.beenLong();
180 | * | vaultInfo.positionIsClosed = perpVault.positionIsClosed();
181 | * | vaultInfo.gmxLock = perpVault.isLock();
182 | * | vaultInfo.isBusy = perpVault.isBusy();
183 | * | vaultInfo.isLocked = perpVault.isLock();
184 | |
185 | * | vaultInfo.treasuryBalance = USDC.balanceOf(perpVault.treasury());
186 | * | vaultInfo.vaultUSDCBalance = USDC.balanceOf(vault);
187 | | }
188 | | }
189 | * | function _snapPositionState(uint8 stateIndex) internal {
190 | | //checking for position instead of full market
191 | | //not to mix vault fees with other players in the market
192 | * | State storage state = states[stateIndex];
193 | |
194 | * | for (uint i = 0; i < VAULTS.length; i++) {
195 | * | address vault = VAULTS[i];
196 | * | PerpetualVault perpVault = PerpetualVault(vault);
197 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault];
198 | |
199 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
200 | * | ReaderUtils.PositionInfo memory positionInfo;
201 | * | try
202 | * | reader.getPositionInfo(
203 | * | dataStore,
204 | * | referralStorage,
205 | * | PerpetualVault(vault).curPositionKey(),
206 | * | _getMarketPrices(
207 | * | vaultToMarket[vault],
208 | * | _setTokenPrices(5000e4)
209 | | ), //any price, checking for collateral
210 | * | uint256(0),
211 | * | address(0),
212 | * | true
213 | | )
214 | * | returns (ReaderUtils.PositionInfo memory return_positionInfo) {
215 | * | positionInfo = return_positionInfo;
216 | | } catch {
217 | | // Handle the error
218 | | }
219 | * | vaultInfo.totalFees = positionInfo
220 | | .fees
221 | | .funding
222 | | .claimableShortTokenAmount;
223 | | }
224 | | }
225 | | }
226 | * | function _snapDepositState(
227 | | address user,
228 | | address market
229 | * | ) internal returns (DepositState memory state) {
230 | * | Market.Props memory marketProps = MarketStoreUtils.get(
231 | * | dataStore,
232 | * | market
233 | | );
234 | |
235 | * | state.userBalanceMarket = ERC20(market).balanceOf(user);
236 | * | state.vaultBalanceLong = ERC20(marketProps.longToken).balanceOf(
237 | * | address(depositVault)
238 | | );
239 | * | state.vaultBalanceShort = ERC20(marketProps.shortToken).balanceOf(
240 | * | address(depositVault)
241 | | );
242 | * | state.marketTotalSupply = ERC20(market).totalSupply();
243 | |
244 | * | state.userBalanceLong = ERC20(marketProps.longToken).balanceOf(user);
245 | |
246 | * | state.userBalanceShort = ERC20(marketProps.shortToken).balanceOf(user);
247 | | }
248 | |
249 | | function _snapShiftState(
250 | | address user,
251 | | address marketFrom,
252 | | address marketTo
253 | | ) internal returns (ShiftState memory state) {
254 | | state.marketToBalance = ERC20(marketTo).balanceOf(user);
255 | | state.marketFromBalance = ERC20(marketFrom).balanceOf(user);
256 | |
257 | | Market.Props memory marketFromProps = MarketStoreUtils.get(
258 | | dataStore,
259 | | marketFrom
260 | | );
261 | | Market.Props memory marketToProps = MarketStoreUtils.get(
262 | | dataStore,
263 | | marketTo
264 | | );
265 | |
266 | | state.longTokenPoolAmountMarketFrom = _getPoolAmount(
267 | | dataStore,
268 | | marketFromProps,
269 | | marketFromProps.longToken
270 | | );
271 | |
272 | | state.shortTokenPoolAmountMarketFrom = _getPoolAmount(
273 | | dataStore,
274 | | marketFromProps,
275 | | marketFromProps.shortToken
276 | | );
277 | |
278 | | state.longTokenPoolAmountMarketTo = _getPoolAmount(
279 | | dataStore,
280 | | marketToProps,
281 | | marketToProps.longToken
282 | | );
283 | |
284 | | state.shortTokenPoolAmountMarketTo = _getPoolAmount(
285 | | dataStore,
286 | | marketToProps,
287 | | marketToProps.shortToken
288 | | );
289 | |
290 | | state.longTokenMarketFeeAmountMarketFrom = _getClaimableFeeAmount(
291 | | marketFrom,
292 | | marketFromProps.longToken
293 | | );
294 | |
295 | | state.shortTokenMarketFeeAmountMarketFrom = _getClaimableFeeAmount(
296 | | marketTo,
297 | | marketFromProps.shortToken
298 | | );
299 | |
300 | | return state;
301 | | }
302 | |
303 | | function _depositPreconditions(
304 | | uint8 userIndex,
305 | | uint8 marketIndex
306 | | ) internal {
307 | | address market = _getMarketAddress(marketIndex);
308 | | Market.Props memory marketProps = MarketStoreUtils.get(
309 | | dataStore,
310 | | market
311 | | );
312 | | address user = _getRandomUser(userIndex);
313 | |
314 | | require(
315 | | ERC20(marketProps.marketToken).balanceOf(user) == 0,
316 | | "FuzzEchidna:: Fresh depositors only" // @coverage: limiter
317 | | );
318 | | }
319 | |
320 | * | function _snapPositionState(
321 | | bytes32 positionKey,
322 | | OrderCreated memory order
323 | * | ) internal returns (PositionState memory) {
324 | | /*
325 | | ,___,
326 | | [O.o]
327 | | /)__)
328 | | "--" This market props are for the POSITION
329 | | NOTE: when cancelling order, position is empty
330 | | */
331 | * | Position.Props memory position = PositionStoreUtils.get(
332 | * | dataStore,
333 | * | positionKey
334 | | );
335 | * | Market.Props memory market = MarketStoreUtils.get(
336 | * | dataStore,
337 | * | position.addresses.market
338 | | );
339 | |
340 | * | PositionState memory state;
341 | * | state.sizeInUsd = position.numbers.sizeInUsd;
342 | * | state.sizeInTokens = position.numbers.sizeInTokens;
343 | * | state.collateralAmount = position.numbers.collateralAmount;
344 | * | state.isLong = position.flags.isLong;
345 | * | state.OILong = dataStore.getUint(
346 | * | Keys.openInterestKey(
347 | * | order.createOrderParams.addresses.market,
348 | * | order.createOrderParams.addresses.initialCollateralToken,
349 | * | true
350 | | )
351 | | );
352 | |
353 | * | address lastAddress = getLastSwapPathAddress(
354 | * | order.createOrderParams.addresses
355 | | );
356 | * | state.OILongLatestMarket = dataStore.getUint(
357 | * | Keys.openInterestKey(
358 | * | lastAddress,
359 | * | order.createOrderParams.addresses.initialCollateralToken,
360 | * | true
361 | | )
362 | | );
363 | |
364 | * | state.OIShort = dataStore.getUint(
365 | * | Keys.openInterestKey(
366 | * | order.createOrderParams.addresses.market,
367 | * | order.createOrderParams.addresses.initialCollateralToken,
368 | * | false
369 | | )
370 | | );
371 | * | state.collateralSumLong = dataStore.getUint(
372 | * | Keys.collateralSumKey(
373 | * | order.createOrderParams.addresses.market,
374 | * | order.createOrderParams.addresses.initialCollateralToken,
375 | * | true
376 | | )
377 | | );
378 | * | state.collateralSumShort = dataStore.getUint(
379 | * | Keys.collateralSumKey(
380 | * | order.createOrderParams.addresses.market,
381 | * | order.createOrderParams.addresses.initialCollateralToken,
382 | * | false
383 | | )
384 | | );
385 | |
386 | | /**
387 | | / This marketProps are for the ORDER
388 | | */
389 | |
390 | * | Market.Props memory marketProps = MarketStoreUtils.get(
391 | * | dataStore,
392 | * | order.createOrderParams.addresses.market
393 | | );
394 | |
395 | * | state.balanceOfLongToken = ERC20(marketProps.longToken).balanceOf(
396 | * | order.createOrderParams.addresses.receiver
397 | | );
398 | |
399 | * | state.balanceOfShortToken = ERC20(marketProps.shortToken).balanceOf(
400 | * | order.createOrderParams.addresses.receiver
401 | | );
402 | |
403 | * | return state;
404 | | }
405 | |
406 | * | function _snapSwapState(
407 | | bool isAfter,
408 | | OrderCreated memory order
409 | * | ) internal returns (SwapState memory) {
410 | * | SwapState memory state;
411 | |
412 | * | state.balanceOfInputToken = ERC20(
413 | * | order.createOrderParams.addresses.initialCollateralToken
414 | * | ).balanceOf(order.createOrderParams.addresses.receiver);
415 | |
416 | * | (, state.outputToken) = _getTokenOut(
417 | * | _getSwapPath(order.swapPathSeed),
418 | * | order.createOrderParams.addresses.initialCollateralToken
419 | | );
420 | |
421 | * | state.balanceOfInputToken = ERC20(
422 | * | order.createOrderParams.addresses.initialCollateralToken
423 | * | ).balanceOf(order.createOrderParams.addresses.receiver);
424 | * | state.balanceOfOutputToken = ERC20(state.outputToken).balanceOf(
425 | * | order.createOrderParams.addresses.receiver
426 | | );
427 | |
428 | * | if (!isAfter) {
429 | * | state.swapResult = _getAmountsOut(
430 | * | order.createOrderParams.addresses.swapPath,
431 | * | order.createOrderParams.addresses.initialCollateralToken,
432 | * | order.createOrderParams.numbers.initialCollateralDeltaAmount,
433 | * | address(0),
434 | * | order.tokenPrices
435 | | );
436 | | }
437 | |
438 | * | if (isAfter) {
439 | * | fl.t(
440 | * | state.outputToken != address(0),
441 | | "Path should be valid at this stage"
442 | | );
443 | | }
444 | * | return state;
445 | | }
446 | * | function getLastSwapPathAddress(
447 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses
448 | * | ) internal pure returns (address) {
449 | * | if (addresses.swapPath.length == 0) return address(0);
450 | | uint256 lastIndex = addresses.swapPath.length - 1;
451 | | return addresses.swapPath[lastIndex];
452 | | }
453 | |
454 | * | function _snapWithdrawalState(
455 | | address user,
456 | | address market
457 | * | ) internal returns (WithdrawalState memory withdrawalState) {
458 | * | Market.Props memory marketProps = MarketStoreUtils.get(
459 | * | dataStore,
460 | * | market
461 | | );
462 | |
463 | * | withdrawalState.userBalance = ERC20(market).balanceOf(user);
464 | * | withdrawalState.vaultBalance = ERC20(market).balanceOf(
465 | * | address(withdrawalVault)
466 | | );
467 | * | withdrawalState.marketTokenTotalSupply = ERC20(market).totalSupply();
468 | * | withdrawalState.longTokenBalanceMarketVault = ERC20(
469 | * | marketProps.longToken
470 | * | ).balanceOf(market);
471 | * | withdrawalState.shortTokenBalanceMarketVault = ERC20(
472 | * | marketProps.shortToken
473 | * | ).balanceOf(market);
474 | * | withdrawalState.longTokenBalanceUser = ERC20(marketProps.longToken)
475 | * | .balanceOf(user);
476 | * | withdrawalState.nativeTokenBalanceUser = address(user).balance;
477 | * | withdrawalState.shortTokenBalanceUser = ERC20(marketProps.shortToken)
478 | * | .balanceOf(user);
479 | | }
480 | | }
481 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/DepositProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../logicalCoverage/DepositCoverage.sol";
6 | |
7 | | contract DepositProperties is DepositCoverage {
8 | * | function invariantDepositedTokensMatchSimulatedAmounts(
9 | | DepositCreated memory depositCreated,
10 | | DepositState memory _after
11 | * | ) internal {
12 | * | uint actualDepositedAmount = _after.userBalanceMarket -
13 | * | depositCreated.beforeDepositExec.userBalanceMarket;
14 | |
15 | * | eqPercentageDiff(
16 | * | depositCreated.beforeDepositExec.simulateDepositAmountOut,
17 | * | actualDepositedAmount,
18 | * | 15e27, //eqPercentageDiff has 1e30 precision
19 | | "DEP-1 Deposited market token amount should be equal amount after simulation."
20 | | );
21 | | }
22 | * | function invariantMarketTokenSupplyIncreases(DepositCreated memory depositCreated) internal {
23 | * | fl.gt(
24 | * | ERC20(depositCreated.createDepositParams.market).totalSupply(),
25 | * | depositCreated.beforeDepositExec.marketTotalSupply,
26 | | "DEP-2 Market tokens total supply should increase"
27 | | );
28 | | }
29 | |
30 | | function _cancelDepositAssertions(
31 | | DepositState memory _before,
32 | | DepositState memory _after,
33 | | DepositCreated memory depositCreated
34 | | ) internal {
35 | | uint gasFeePaidForExecution = FIXED_EXECUTION_FEE_AMOUNT - address(callback).balance;
36 | |
37 | | Market.Props memory market = MarketStoreUtils.get(
38 | | dataStore,
39 | | depositCreated.createDepositParams.market
40 | | );
41 | |
42 | | require(
43 | | market.longToken != market.shortToken,
44 | | "Assertions are not suitable for homogenic markets"
45 | | );
46 | |
47 | | fl.eq(
48 | | _before.userBalanceMarket,
49 | | _after.userBalanceMarket,
50 | | "CNCL-DEP-01 User market token amounts should stay unchanged"
51 | | );
52 | |
53 | | if (depositCreated.depositorParams.longAmount > 0) {
54 | | fl.lte(
55 | | _after.userBalanceLong,
56 | | _before.userBalanceLong +
57 | | depositCreated.depositorParams.longAmount +
58 | | gasFeePaidForExecution,
59 | | "CNCL-DEP-02 User long token amounts after cancel should be less or equal balance before plus deposited amount"
60 | | );
61 | |
62 | | eqPercentageDiff(
63 | | _after.userBalanceLong,
64 | | _before.userBalanceLong + depositCreated.depositorParams.longAmount,
65 | | 1e27, //dust
66 | | "CNCL-DEP-03 User long token amounts should stay unchanged"
67 | | );
68 | |
69 | | eqPercentageDiff(
70 | | _before.vaultBalanceLong -
71 | | depositCreated.depositorParams.longAmount -
72 | | (market.longToken == address(WETH) ? FIXED_EXECUTION_FEE_AMOUNT : 0),
73 | | //before cancel tokens are in the vault
74 | | _after.vaultBalanceLong,
75 | | 0, //exact eq
76 | | "CNCL-DEP-04 Vault long token amounts should stay unchanged"
77 | | );
78 | | }
79 | |
80 | | if (depositCreated.depositorParams.shortAmount > 0) {
81 | | fl.lte(
82 | | _after.userBalanceShort,
83 | | _before.userBalanceShort + depositCreated.depositorParams.shortAmount,
84 | | "CNCL-DEP-05 User short token amounts after cancel should be less or equal balance before plus deposited amount"
85 | | );
86 | |
87 | | eqPercentageDiff(
88 | | _after.userBalanceShort,
89 | | _before.userBalanceShort + depositCreated.depositorParams.shortAmount,
90 | | 1e27, //dust
91 | | "CNCL-DEP-06 User short token amounts should stay unchanged"
92 | | );
93 | |
94 | | eqPercentageDiff(
95 | | _before.vaultBalanceShort - depositCreated.depositorParams.shortAmount,
96 | | _after.vaultBalanceShort,
97 | | 1e27,
98 | | "CNCL-DEP-07 Vault short token amounts should stay unchanged"
99 | | );
100 | | }
101 | | }
102 | | }
103 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/LiquidationProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../logicalCoverage/LiquidationCoverage.sol";
6 | |
7 | | contract LiquidationProperties is LiquidationCoverage {
8 | * | function invariantPositionCountShouldDecrease(
9 | | uint positionCountAfter,
10 | | uint positionCountBefore
11 | | ) internal {
12 | * | fl.lt(
13 | * | positionCountAfter,
14 | * | positionCountBefore,
15 | | "LIQ-01: Position count not decreased post-liquidation"
16 | | );
17 | | }
18 | |
19 | * | function invariantAutoCancelListShouldBeEmptyAfterLiquidation(
20 | | uint autoCancelOrderKeysLength
21 | | ) internal {
22 | * | fl.eq(
23 | * | autoCancelOrderKeysLength,
24 | * | 0,
25 | | "LIQ-02: Auto cancel order list non-empty post-liquidation"
26 | | );
27 | | }
28 | |
29 | * | function invariantPositionCountDecreasesByOne(
30 | | uint positionCountAfter,
31 | | uint positionCountBefore
32 | | ) internal {
33 | * | fl.eq(
34 | * | positionCountAfter + 1,
35 | * | positionCountBefore,
36 | | "LIQ-03: Position count should be decreased by 1"
37 | | );
38 | | }
39 | | }
40 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/PositionProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "../logicalCoverage/PositionCoverage.sol";
5 | |
6 | | contract PositionProperties is PositionCoverage {
7 | * | function _increaseAssertions(
8 | | PositionState memory _before,
9 | | PositionState memory _after,
10 | | OrderCreated memory order
11 | * | ) internal {
12 | * | uint sizeDelta = order.createOrderParams.numbers.sizeDeltaUsd;
13 | * | uint collateralDelta = order
14 | | .createOrderParams
15 | | .numbers
16 | | .initialCollateralDeltaAmount;
17 | |
18 | * | if (sizeDelta > 0)
19 | *r | require(
20 | * | _after.sizeInUsd > _before.sizeInUsd,
21 | | "INC-01: Position size usd did not increase"
22 | | );
23 | * | if (collateralDelta > 0)
24 | * | require(
25 | * | _after.collateralAmount > _before.collateralAmount,
26 | | "INC-03: Collateral amount did not increase"
27 | | );
28 | | }
29 | |
30 | | function _decreaseAssertions(
31 | | PositionState memory _before,
32 | | PositionState memory _after,
33 | | OrderCreated memory order
34 | | ) internal {
35 | | uint sizeDelta = order.createOrderParams.numbers.sizeDeltaUsd;
36 | | uint collateralDelta = order
37 | | .createOrderParams
38 | | .numbers
39 | | .initialCollateralDeltaAmount;
40 | |
41 | | if (sizeDelta > 0)
42 | | require(
43 | | _after.sizeInUsd < _before.sizeInUsd,
44 | | "DEC-01: Position size usd did not decrease"
45 | | );
46 | | if (collateralDelta > 0)
47 | | require(
48 | | _after.collateralAmount < _before.collateralAmount,
49 | | "DEC-02: Collateral amount did not decrease"
50 | | );
51 | | if (_after.sizeInUsd == 0) {
52 | | bytes32 positionKey = Position.getPositionKey(
53 | | order.createOrderParams.addresses.receiver,
54 | | order.createOrderParams.addresses.market,
55 | | order.createOrderParams.addresses.initialCollateralToken,
56 | | order.createOrderParams.isLong
57 | | );
58 | | Position.Props memory positionAfter = PositionStoreUtils.get(
59 | | dataStore,
60 | | positionKey
61 | | );
62 | | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils
63 | | .getAutoCancelOrderKeys(dataStore, positionKey);
64 | | fl.eq(
65 | | positionAfter.numbers.sizeInUsd,
66 | | 0,
67 | | "CLOSE-01: Position still has size in USD after closing"
68 | | );
69 | | fl.eq(
70 | | positionAfter.numbers.sizeInTokens,
71 | | 0,
72 | | "CLOSE-02: Position still has size in tokens after closing"
73 | | );
74 | | fl.eq(
75 | | positionAfter.numbers.collateralAmount,
76 | | 0,
77 | | "CLOSE-03: Position still has collateral after closing"
78 | | );
79 | | fl.eq(
80 | | autoCancelOrderKeys.length,
81 | | 0,
82 | | "CLOSE-04: Auto cancel order list non-empty after closing position"
83 | | );
84 | | }
85 | | if (order.createOrderParams.isLong) {
86 | | fl.lte(
87 | | _after.OILong,
88 | | _before.OILong - sizeDelta,
89 | | "DEC-03: Long OI did not decrease"
90 | | );
91 | | fl.lte(
92 | | _after.collateralSumLong,
93 | | _before.collateralSumLong - collateralDelta,
94 | | "DEC-04: Collateral sum long did not decrease"
95 | | );
96 | | } else {
97 | | fl.lte(
98 | | _after.OIShort,
99 | | _before.OIShort - sizeDelta,
100 | | "DEC-03: Short OI did not decrease"
101 | | );
102 | |
103 | | fl.lte(
104 | | _after.collateralSumShort,
105 | | _before.collateralSumShort - collateralDelta,
106 | | "DEC-04: Collateral sum short did not decrease"
107 | | );
108 | | }
109 | | }
110 | |
111 | | function _cancelOrderAssertions(
112 | | PositionState memory _before,
113 | | PositionState memory _after,
114 | | OrderCreated memory order
115 | | ) internal {
116 | | if (order.createOrderParams.isLong) {
117 | | eqPercentageDiff(
118 | | _after.balanceOfLongToken,
119 | | _before.balanceOfLongToken + order.amountSent,
120 | | 1e28, //1%
121 | | "CNCL-ORD-1: User should receive the same amount of long tokens he sent to create an order"
122 | | );
123 | | } else {
124 | | eqPercentageDiff(
125 | | _after.balanceOfShortToken,
126 | | _before.balanceOfShortToken + order.amountSent,
127 | | 1e28, //1%
128 | | "CNCL-ORD-2: User should receive the same amount of short tokens he sent to create an order"
129 | | );
130 | | }
131 | | }
132 | | //NOTE: excluded in GAMMA, require next level of intergration with GMX source code changes
133 | * | function _swapAssertions(
134 | | SwapState memory _before,
135 | | SwapState memory _after,
136 | | OrderCreated memory order
137 | | ) internal {
138 | | // eqPercentageDiff(
139 | | // _after.balanceOfOutputToken,
140 | | // _before.balanceOfOutputToken + _before.swapResult.amountOut,
141 | | // 1e27,
142 | | // "SWP-01 Received token balance after swap should be equal to simulated amounts before swap."
143 | | // );
144 | | }
145 | | }
146 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/Properties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./ShiftProperties.sol";
6 | | import "./PositionProperties.sol";
7 | | import "./WithdrawalProperties.sol";
8 | | import "./DepositProperties.sol";
9 | | import "./LiquidationProperties.sol";
10 | | import "./ADLProperties.sol";
11 | |
12 | | contract Properties is
13 | | ShiftProperties,
14 | | PositionProperties,
15 | | WithdrawalProperties,
16 | | DepositProperties,
17 | | LiquidationProperties,
18 | | ADLProperties
19 | | {
20 | | uint256 internal TEN_THOUSAND = 10_000;
21 | |
22 | * | function gammaGeneralPostconditions(
23 | | address vault,
24 | | uint priceSeed
25 | | ) internal {
26 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) {
27 | | //NOTE: assume successfull execution
28 | * | _invariant_GAMMA_03(vault);
29 | * | _invariant_GAMMA_04(vault);
30 | * | _invariant_GAMMA_05(vault);
31 | * | _invariant_GAMMA_06(vault, priceSeed);
32 | * | _invariant_GAMMA_09(vault);
33 | * | _invariant_GAMMA_10(vault);
34 | | }
35 | | }
36 | |
37 | * | function _invariant_GAMMA_02(address vault) internal {
38 | * | fl.eq(
39 | * | states[1].vaultInfos[vault].totalShares,
40 | * | states[1].vaultInfos[vault].totalSharesCalculated,
41 | | "GAMMA-2"
42 | | );
43 | | }
44 | * | function _invariant_GAMMA_03(address vault) internal {
45 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) {
46 | * | VaultInfo storage vaultInfoBefore = states[0].vaultInfos[vault];
47 | * | VaultInfo storage vaultInfoAfter = states[1].vaultInfos[vault];
48 | |
49 | * | uint256 vaultShareValueBefore = vaultInfoBefore.shareValue;
50 | | //preventing false positives when value share % changes
51 | | //from 1wei to 1e15 by introducing arbitrary low precision treshold
52 | * | if (
53 | * | vaultInfoBefore.vaultUSDCBalance +
54 | * | vaultInfoBefore.collateralAmount >
55 | * | 1e3
56 | * | ) {
57 | * | uint256 vaultShareValueAfter = vaultInfoAfter.shareValue;
58 | * | if (vaultShareValueAfter != 0) {
59 | * | int256 vaultShareValueChangePercentage;
60 | * | if (vaultShareValueBefore == 0) {
61 | | vaultShareValueChangePercentage = 0;
62 | * | } else {
63 | * | int256 difference = int256(vaultShareValueAfter) -
64 | * | int256(vaultShareValueBefore);
65 | * | if (
66 | * | abs(difference) * 10000 < vaultShareValueBefore * 5
67 | | ) {
68 | | //gmx fees
69 | | // Change is less than 0.05%, consider it as no change
70 | * | vaultShareValueChangePercentage = 0;
71 | * | } else if (
72 | * | vaultShareValueAfter >= vaultShareValueBefore
73 | | ) {
74 | * | vaultShareValueChangePercentage = int256(
75 | * | ((vaultShareValueAfter * 1e30) /
76 | * | vaultShareValueBefore) - 1e30
77 | | );
78 | | } else {
79 | * | vaultShareValueChangePercentage = -int256(
80 | * | ((vaultShareValueBefore * 1e30) /
81 | * | vaultShareValueAfter) - 1e30
82 | | );
83 | | }
84 | | }
85 | |
86 | * | uint256 userSharesChangedCount = 0;
87 | * | for (uint i = 0; i < USERS.length; i++) {
88 | * | address checkUser = USERS[i];
89 | * | UserState storage userStateBefore = vaultInfoBefore
90 | * | .userStates[checkUser];
91 | * | UserState storage userStateAfter = vaultInfoAfter
92 | * | .userStates[checkUser];
93 | * | if (
94 | * | userStateBefore.totalShares !=
95 | * | userStateAfter.totalShares
96 | | ) {
97 | | userSharesChangedCount++;
98 | | }
99 | * | if (
100 | * | userStateBefore.totalShares > 0 &&
101 | * | userStateAfter.totalShares > 0
102 | * | ) {
103 | * | int256 userShareValueChangePercentage;
104 | * | if (userStateBefore.shareValue == 0) {
105 | | userShareValueChangePercentage = 0;
106 | * | } else {
107 | * | int256 difference = int256(
108 | * | userStateAfter.shareValue
109 | * | ) - int256(userStateBefore.shareValue);
110 | * | if (
111 | * | abs(difference) * 10000 <
112 | * | userStateBefore.shareValue * 5
113 | | ) {
114 | | // Change is less than 0.05%, consider it as no change
115 | * | userShareValueChangePercentage = 0;
116 | * | } else if (
117 | * | userStateAfter.shareValue >=
118 | * | userStateBefore.shareValue
119 | | ) {
120 | * | userShareValueChangePercentage = int256(
121 | * | ((userStateAfter.shareValue * 1e30) /
122 | * | userStateBefore.shareValue) - 1e30
123 | | );
124 | | } else {
125 | * | userShareValueChangePercentage = -int256(
126 | * | ((userStateBefore.shareValue * 1e30) /
127 | * | userStateAfter.shareValue) - 1e30
128 | | );
129 | | }
130 | | }
131 | |
132 | * | if (vaultShareValueChangePercentage > 1e28) {
133 | | //too small vault value change will not be seen on user share value change
134 | * | eqPercentageDiff(
135 | * | uint256(userShareValueChangePercentage),
136 | * | uint256(vaultShareValueChangePercentage),
137 | * | 3e27, // some presision tolerance
138 | | "GAMMA-3"
139 | | );
140 | | }
141 | | }
142 | | }
143 | * | fl.lte(
144 | * | userSharesChangedCount,
145 | * | 1,
146 | | "GAMMA-3: Multiple users' shares changed unexpectedly"
147 | | );
148 | | }
149 | | }
150 | | }
151 | | }
152 | * | function _invariant_GAMMA_04(address vault) internal {
153 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) {
154 | * | (PerpetualVault.NextActionSelector selector, ) = PerpetualVault(
155 | * | vault
156 | | ).nextAction();
157 | * | selector == PerpetualVault.NextActionSelector.NO_ACTION;
158 | * | fl.t(
159 | * | selector == PerpetualVault.NextActionSelector.NO_ACTION,
160 | | "GAMMA-4"
161 | | );
162 | | }
163 | | }
164 | |
165 | * | function _invariant_GAMMA_05(address vault) internal {
166 | | //After all execution stages
167 | * | (uint swappedData, uint remainingData) = PerpetualVaultLens(vault)
168 | | ._getSwapProgress();
169 | * | fl.t(swappedData == 0 && remainingData == 0, "GAMMA-5");
170 | | }
171 | |
172 | * | function _invariant_GAMMA_06(address vault, uint priceSeed) internal {
173 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices(
174 | * | vaultToMarket[vault],
175 | * | priceSeed
176 | | );
177 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
178 | * | (, , uint256 sizeInUsd, , , , ) = PerpetualVault(vault)
179 | * | .getPositionInfo(convertedPrices);
180 | |
181 | * | fl.neq(sizeInUsd, 0, "GAMMA-06");
182 | | }
183 | | }
184 | |
185 | * | function _invariant_GAMMA_08(address vault, uint priceSeed) internal {
186 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices(
187 | * | vaultToMarket[vault],
188 | * | priceSeed
189 | | );
190 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) {
191 | * | (, , uint256 sizeInUsd, , , , ) = PerpetualVault(vault)
192 | * | .getPositionInfo(convertedPrices);
193 | |
194 | * | if (sizeInUsd != 0) {
195 | * | fl.t(!PerpetualVault(vault).positionIsClosed(), "GAMMA-08");
196 | | }
197 | | }
198 | | }
199 | |
200 | * | function _invariant_GAMMA_09(address vault) internal {
201 | * | fl.t(uint(PerpetualVault(vault).flow()) == 0, "GAMMA-09");
202 | | }
203 | |
204 | * | function _invariant_GAMMA_10(address vault) internal {
205 | *r | fl.t(PerpetualVaultLens(vault)._getGMXLock() == false, "GAMMA-10");
206 | | }
207 | |
208 | * | function invariantDoesNotSilentRevert(bytes memory returnData) internal {
209 | * | fl.gte(returnData.length, 4, "GLOBAL-1 Should not silent revert");
210 | *r | revert(toHexString(returnData));
211 | | }
212 | |
213 | * | function _invariant_GAMMA_12(address vault, address user) internal {
214 | * | if (!PerpetualVaultLens(vault).cancellationTriggered() == false) {
215 | | fl.gt(
216 | | states[1].vaultInfos[vault].userStates[user].totalShares,
217 | | states[0].vaultInfos[vault].userStates[user].totalShares,
218 | | "GAMMA-12: If user deposits they will get a non-zero amount of shares"
219 | | );
220 | | }
221 | | }
222 | |
223 | | function isLongOneLeverage(
224 | | bool _isLong,
225 | | uint256 _leverage
226 | | ) internal returns (bool) {
227 | | return _isLong && _leverage == TEN_THOUSAND;
228 | | }
229 | | }
230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/ShiftProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../logicalCoverage/ShiftCoverage.sol";
6 | |
7 | | contract ShiftProperties is ShiftCoverage {
8 | | function invariantFromAndToMarketTokenBalancesUpdated(
9 | | ShiftState memory _after,
10 | | ShiftState memory _before
11 | | ) internal {
12 | | require(
13 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket,
14 | | "Invalid invariant for the same market shifting"
15 | | );
16 | | address marketFrom = _after.createShiftParams.fromMarket;
17 | |
18 | | uint marketFromTokenBalanceAfterShift = ERC20(marketFrom).balanceOf(_after.user);
19 | |
20 | | TokenPrices memory tokenPrices = _after.tokenPrices;
21 | |
22 | | address marketTo = _after.createShiftParams.toMarket;
23 | | Market.Props memory marketToProps = MarketStoreUtils.get(dataStore, marketTo);
24 | |
25 | | /**
26 | | __
27 | | ( o>
28 | | /// \ @coverage:limiter
29 | | \V_/_ this is literally the second deposit
30 | |
31 | |
32 | | */
33 | |
34 | | uint simulateDepositAmountOut = ReaderDepositUtils.getDepositAmountOut(
35 | | dataStore,
36 | | marketToProps,
37 | | _getMarketPrices(marketTo, tokenPrices),
38 | | _after.marketDataBefore.simulateLongTokenAmountWithdrawal,
39 | | _after.marketDataBefore.simulateShortTokenAmountWithdrawal,
40 | | address(0),
41 | | ISwapPricingUtils.SwapPricingType.Shift, // TwoStep, Shift, Atomic
42 | | true //includeVirtualInventoryImpact, removed in 7602ff95489fb032e4eeb59d81125d5f3d93e976
43 | | );
44 | |
45 | | fl.lt(
46 | | marketFromTokenBalanceAfterShift,
47 | | _before.marketFromBalance,
48 | | "SHFT-1 User balance of `from` GM tokens decreases upon shift"
49 | | );
50 | | uint marketToTokenBalanceAfterShift = ERC20(marketTo).balanceOf(_after.user);
51 | |
52 | | eqPercentageDiff(
53 | | marketToTokenBalanceAfterShift, //15
54 | | _before.marketToBalance + simulateDepositAmountOut, //30
55 | | 1e28,
56 | | "SHFT-2 User balance of to market GM += shift.marketTokenAmount()"
57 | | );
58 | |
59 | | fl.eq(
60 | | marketFromTokenBalanceAfterShift,
61 | | _before.marketFromBalance - _after.marketTokenAmount,
62 | | "SHFT-3 User balance of from market GM -= shift.marketTokenAmount()"
63 | | );
64 | | }
65 | | function invariantClaimableFeesUnchangedAfterShift(
66 | | ShiftState memory _after,
67 | | ShiftState memory _before
68 | | ) internal {
69 | | address marketFrom = _after.createShiftParams.fromMarket;
70 | | Market.Props memory marketFromProps = MarketStoreUtils.get(dataStore, marketFrom);
71 | |
72 | | uint longTokenMarketFeeAmountAfterMarketFrom = _getClaimableFeeAmount(
73 | | marketFrom,
74 | | marketFromProps.longToken
75 | | );
76 | | uint shortTokenMarketFeeAmountAfterMarketFrom = _getClaimableFeeAmount(
77 | | marketFrom,
78 | | marketFromProps.shortToken
79 | | );
80 | |
81 | | fl.eq(
82 | | _before.longTokenMarketFeeAmountMarketFrom,
83 | | longTokenMarketFeeAmountAfterMarketFrom,
84 | | "SHFT-4 Claimable fees for long token do not change upon shift."
85 | | );
86 | | fl.eq(
87 | | _before.shortTokenMarketFeeAmountMarketFrom,
88 | | shortTokenMarketFeeAmountAfterMarketFrom,
89 | | "SHFT-5 Claimable fees for short token do not change upon shift."
90 | | );
91 | | }
92 | |
93 | | function invariantFromMarketPoolAmountsDecrease(
94 | | ShiftState memory _after,
95 | | ShiftState memory _before
96 | | ) internal {
97 | | require(
98 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket,
99 | | "Invalid assertion for the same market shifting"
100 | | );
101 | |
102 | | address marketFrom = _after.createShiftParams.fromMarket;
103 | |
104 | | Market.Props memory marketFromProps = MarketStoreUtils.get(dataStore, marketFrom);
105 | |
106 | | uint longTokenPoolAmountAfterMarketFrom = _getPoolAmount(
107 | | dataStore,
108 | | marketFromProps,
109 | | marketFromProps.longToken
110 | | );
111 | |
112 | | uint shortTokenPoolAmountAfterMarketFrom = _getPoolAmount(
113 | | dataStore,
114 | | marketFromProps,
115 | | marketFromProps.shortToken
116 | | );
117 | |
118 | | if (_after.marketDataBefore.simulateLongTokenAmountWithdrawal != 0) {
119 | | fl.lt(
120 | | longTokenPoolAmountAfterMarketFrom,
121 | | _before.longTokenPoolAmountMarketFrom,
122 | | "SHFT-6 Long token pool Amount For `from` market should decrease"
123 | | );
124 | | }
125 | | if (_after.marketDataBefore.simulateShortTokenAmountWithdrawal != 0) {
126 | | fl.lt(
127 | | shortTokenPoolAmountAfterMarketFrom,
128 | | _before.shortTokenPoolAmountMarketFrom,
129 | | "SHFT-7 Short token Amount For `from` market should decrease"
130 | | );
131 | | }
132 | | }
133 | |
134 | | function invariantToMarketPoolAmountsIncrease(
135 | | ShiftState memory _after,
136 | | ShiftState memory _before
137 | | ) internal {
138 | | require(
139 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket,
140 | | "Invalid assertion for the same market shifting"
141 | | );
142 | | address marketTo = _after.createShiftParams.toMarket;
143 | |
144 | | Market.Props memory marketToProps = MarketStoreUtils.get(dataStore, marketTo);
145 | |
146 | | uint toMarketLongTokenPoolAmount = _getPoolAmount(
147 | | dataStore,
148 | | marketToProps,
149 | | marketToProps.longToken
150 | | );
151 | | uint toMarketShortTokenPoolAmount = _getPoolAmount(
152 | | dataStore,
153 | | marketToProps,
154 | | marketToProps.shortToken
155 | | );
156 | | if (_after.marketDataBefore.simulateLongTokenAmountWithdrawal != 0) {
157 | | fl.gt(
158 | | toMarketLongTokenPoolAmount,
159 | | _before.longTokenPoolAmountMarketTo,
160 | | "SHFT-8 Pool Amount For `to` market long token should increase"
161 | | );
162 | | }
163 | |
164 | | if (_after.marketDataBefore.simulateShortTokenAmountWithdrawal != 0) {
165 | | fl.gt(
166 | | toMarketShortTokenPoolAmount,
167 | | _before.shortTokenPoolAmountMarketTo,
168 | | "SHFT-9 Pool Amount For `to` market short token should increase"
169 | | );
170 | | }
171 | | }
172 | |
173 | | function invariantMarketTokenValuesStaySame(ShiftState memory _after) internal {
174 | | int defaultPriceForMarketToken = 1e30;
175 | |
176 | | if (_after.marketDataBefore.marketTokenPriceTo != defaultPriceForMarketToken) {
177 | | eqPercentageDiff(
178 | | uint(_after.marketDataBefore.marketTokenPriceFrom),
179 | | uint(_after.marketDataAfter.marketTokenPriceFrom),
180 | | 1e26,
181 | | "SHFT-10 Market token (GM) value for `from` market stays the same after shift execution."
182 | | );
183 | |
184 | | eqPercentageDiff(
185 | | uint(_after.marketDataBefore.marketTokenPriceTo),
186 | | uint(_after.marketDataAfter.marketTokenPriceTo),
187 | | 1e26,
188 | | "SHFT-11 Market token (GM) value for `to` market stays the same after shift execution."
189 | | );
190 | | }
191 | | }
192 | |
193 | | function _cancelShiftAssertions(
194 | | ShiftState memory _before,
195 | | ShiftState memory _after,
196 | | ShiftCreated memory shiftToCancel
197 | | ) internal {
198 | | eqPercentageDiff(
199 | | _after.marketFromBalance,
200 | | _before.marketFromBalance + shiftToCancel.marketTokenAmount,
201 | | 0,
202 | | "CNCL-SHFT-01 Market from received amount should be less or equal than before"
203 | | );
204 | | fl.eq(
205 | | _after.marketToBalance,
206 | | _before.marketToBalance,
207 | | "CNCL-SHFT-02 Market to balance should stay unchanged"
208 | | );
209 | | }
210 | | }
211 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/WithdrawalProperties.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../logicalCoverage/WithdrawalCoverage.sol";
6 | |
7 | | contract WithdrawalProperties is WithdrawalCoverage {
8 | | struct Cache {
9 | | uint256 userDepositAmount;
10 | | uint256 vaultValueBefore;
11 | | uint256 vaultValueAfter;
12 | | uint256 userBalanceBefore;
13 | | uint256 userBalanceAfter;
14 | | uint256 withdrawnAmount;
15 | | uint256 depositedAmount;
16 | | uint256 userShareBefore;
17 | | uint256 totalWithdrawn;
18 | | uint256 totalFeesBefore;
19 | | uint256 totalFeesAfter;
20 | | uint256 userFairShareOfFees;
21 | | uint256 userActualFees;
22 | | uint256 treasuryBalanceBefore;
23 | | uint256 treasuryBalanceAfter;
24 | | uint256 treasuryFees;
25 | | }
26 | |
27 | | function _invariant_GAMMA_01(
28 | | uint8 userSeed,
29 | | uint8 vaultSeed,
30 | | uint initialDepositAmount
31 | | ) internal {
32 | | Cache memory cache;
33 | |
34 | | address user = _getRandomUser(userSeed);
35 | | (address vault, , , ) = _gamma_getVault(vaultSeed);
36 | |
37 | | cache.userBalanceBefore = states[0]
38 | | .vaultInfos[vault]
39 | | .userStates[user]
40 | | .USDCBalance;
41 | | cache.userBalanceAfter = states[1]
42 | | .vaultInfos[vault]
43 | | .userStates[user]
44 | | .USDCBalance;
45 | |
46 | | cache.withdrawnAmount =
47 | | cache.userBalanceAfter -
48 | | cache.userBalanceBefore;
49 | |
50 | | cache.treasuryBalanceBefore = states[0]
51 | | .vaultInfos[vault]
52 | | .treasuryBalance;
53 | | cache.treasuryBalanceAfter = states[1]
54 | | .vaultInfos[vault]
55 | | .treasuryBalance;
56 | | cache.treasuryFees =
57 | | cache.treasuryBalanceAfter -
58 | | cache.treasuryBalanceBefore;
59 | |
60 | | cache.withdrawnAmount = cache.withdrawnAmount + cache.treasuryFees; //NOTE: we are taking fees into calculation for a fair share
61 | |
62 | | cache.depositedAmount = states[0].vaultInfos[vault].totalAmount;
63 | |
64 | | cache.userDepositAmount = initialDepositAmount;
65 | |
66 | | cache.userShareBefore =
67 | | (cache.userDepositAmount * 1e30) /
68 | | cache.depositedAmount;
69 | |
70 | | cache.totalFeesBefore = states[0].vaultInfos[vault].totalFees;
71 | | cache.totalFeesAfter = states[1].vaultInfos[vault].totalFees;
72 | |
73 | | if (cache.totalFeesBefore > 0 && cache.totalFeesAfter == 0) {
74 | | cache.userFairShareOfFees =
75 | | (cache.totalFeesBefore * cache.userShareBefore) /
76 | | 1e30;
77 | |
78 | | cache.userActualFees =
79 | | cache.withdrawnAmount -
80 | | cache.userDepositAmount;
81 | |
82 | | eqPercentageDiff(
83 | | uint256(cache.userFairShareOfFees),
84 | | uint256(cache.userActualFees),
85 | | 1e25, //super small tolerance for precision
86 | | "GAMMA-1"
87 | | );
88 | | }
89 | | }
90 | |
91 | | function _invariant_GAMMA_07(
92 | | address vault,
93 | | uint depositTimestamp
94 | | ) internal {
95 | | fl.gte(
96 | | block.timestamp + PerpetualVault(vault).lockTime() + 1,
97 | | depositTimestamp,
98 | | "GAMMA-7"
99 | | );
100 | | }
101 | |
102 | | function invariantWithdrawnTokensMatchSimulatedAmounts(
103 | | WithdrawalState memory _before,
104 | | WithdrawalState memory _after,
105 | | WithdrawalCreated memory withdrawalCreated
106 | | ) internal {
107 | | Market.Props memory marketProps = MarketStoreUtils.get(
108 | | dataStore,
109 | | withdrawalCreated.withdrawalParams.market
110 | | );
111 | | if (marketProps.longToken != marketProps.shortToken) {
112 | | eqPercentageDiff(
113 | | _before.longTokenBalanceUser +
114 | | _before.simulateLongTokenAmountWithdrawal,
115 | | _after.longTokenBalanceUser,
116 | | 1e27,
117 | | "WITHD-1 Withdrawn long token amount should be equal amount after simulation."
118 | | );
119 | |
120 | | eqPercentageDiff(
121 | | _before.shortTokenBalanceUser +
122 | | _before.simulateShortTokenAmountWithdrawal,
123 | | _after.shortTokenBalanceUser,
124 | | 1e27,
125 | | "WITHD-2 Withdrawn short token amount should be equal amount after simulation."
126 | | );
127 | | }
128 | | }
129 | |
130 | | function invariantMarketTokenSupplyDecreases(
131 | | WithdrawalState memory _before,
132 | | WithdrawalState memory _after
133 | | ) internal {
134 | | fl.lt(
135 | | _after.marketTokenTotalSupply,
136 | | _before.marketTokenTotalSupply,
137 | | "WITH-3 Market tokens total supply should decrease"
138 | | );
139 | | }
140 | * | function _cancelWithdrawalAssertions(
141 | | WithdrawalState memory _before,
142 | | WithdrawalState memory _after,
143 | | WithdrawalCreated memory withdrawalToCancel
144 | | ) internal {
145 | * | eqPercentageDiff(
146 | * | _after.userBalance,
147 | * | _before.userBalance + withdrawalToCancel.amount,
148 | * | 1e27,
149 | | "CNCL-WITH-1 User should receive market tokens back after cancelling withdrawal"
150 | | );
151 | * | fl.eq(
152 | * | _after.marketTokenTotalSupply,
153 | * | _before.marketTokenTotalSupply,
154 | | "CNCL-WITH-2 Market tokens total supply should stay the same"
155 | | );
156 | |
157 | * | eqPercentageDiff(
158 | * | _after.vaultBalance,
159 | * | _before.vaultBalance - withdrawalToCancel.amount,
160 | * | 1e27,
161 | | "CNCL-WITH-3 Vault should refund market tokens. "
162 | | );
163 | | }
164 | | }
165 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzGMXConfig.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/FuzzUtils.sol";
6 | |
7 | | /*
8 | | * Percentage representation:
9 | | * "50%" --> 5e29
10 | | * "1%" --> 1e28
11 | | * "0.1%" --> 1e27
12 | | * "0.01%" --> 1e26
13 | | */
14 | |
15 | * | contract FuzzGMXConfig is FuzzUtils {
16 | | uint256 internal WETH_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000;
17 | | uint256 internal WBTC_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000;
18 | | uint256 internal USDC_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000;
19 | | uint256 internal USDT_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000;
20 | |
21 | | address internal FEE_RECEIVER = address(0);
22 | | address internal HOLDING_ADDRESS = address(0);
23 | |
24 | | uint256 internal MAX_UI_FEE_FACTOR = 50e24;
25 | | uint256 internal MAX_AUTO_CANCEL_ORDERS = 10;
26 | | uint256 internal MIN_HANDLE_EXECUTION_ERROR_GAS = 120 * 1000;
27 | | uint256 internal MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = 1000 * 1000;
28 | | uint256 internal MIN_ADDITIONAL_GAS_FOR_EXECUTION = 1000 * 1000;
29 | | uint256 internal MAX_CALLBACK_GAS_LIMIT = 2000 * 1000;
30 | | uint256 internal MAX_SWAP_PATH_LENGTH = 5;
31 | | uint256 internal MIN_COLLATERAL_USD = 1000e27;
32 | | uint256 internal MIN_POSITION_SIZE_USD = 1000e27;
33 | |
34 | | uint256 internal SWAP_FEE_RECEIVER_FACTOR = 37e28;
35 | | uint256 internal POSITION_FEE_RECEIVER_FACTOR = 0;
36 | | uint256 internal BORROWING_FEE_RECEIVER_FACTOR = 0;
37 | |
38 | | uint256 internal CLAIMABLE_COLLATERAL_TIME_DIVISOR = 3600;
39 | |
40 | | uint256 internal DEPOSIT_GAS_LIMIT = 0;
41 | | uint256 internal WITHDRAWAL_GAS_LIMIT = 0;
42 | | uint256 internal SINGLE_SWAP_GAS_LIMIT = 0;
43 | | uint256 internal INCREASE_ORDER_GAS_LIMIT = 0;
44 | | uint256 internal DECREASE_ORDER_GAS_LIMIT = 0;
45 | | uint256 internal SWAP_ORDER_GAS_LIMIT = 0;
46 | |
47 | | uint256 internal NATIVE_TOKEN_TRANSFER_GAS_LIMIT = 50000;
48 | |
49 | | uint256 internal ESTIMATED_GAS_FEE_BASE_AMOUNT = 1000000;
50 | | uint256 internal ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = 1000000;
51 | | uint256 internal EXECUTION_GAS_FEE_PER_ORACLE_PRICE = 20000;
52 | | uint256 internal EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = 2e30;
53 | | uint256 internal REFUND_EXECUTION_FEE_GAS_LIMIT = 1_000_000;
54 | |
55 | | bool internal SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = false;
56 | | uint256 internal REQUEST_EXPIRATION_TIME = 3600;
57 | |
58 | | uint256 internal MIN_ORACLE_SIGNERS = 0;
59 | |
60 | | int256 internal USDC_INIT_PRICE = 100000000;
61 | | int256 internal USDT_INIT_PRICE = 100000000;
62 | |
63 | | bool internal IS_ORACLE_PROVIDER_ENABLED = true;
64 | | bool internal IS_ATOMIC_ORACLE_PROVIDER = true;
65 | |
66 | | uint256 internal MIN_ORACLE_BLOCK_CONFIRMATIONS = 255;
67 | | uint256 internal MAX_ORACLE_TIMESTAMP_RANGE = 60;
68 | | uint256 internal MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = 5e29;
69 | | address internal CHAINLINK_PAYMENT_TOKEN =
70 | | 0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf;
71 | |
72 | | bytes32 internal ORACLE_TYPE_DEFAULT =
73 | | keccak256(abi.encode("one-percent-per-minute"));
74 | | address internal ORACLE_PROVIDER_FOR_TOKEN;
75 | | uint256 internal PRICE_FEED_MULTIPLIER = 1e46;
76 | | uint256 internal PRICE_FEED_HEARTBEAT_DURATION = 86400;
77 | |
78 | | address SOL = _getSyntheticTokenAddress("SOL");
79 | |
80 | | bytes32 internal DEFAULT_MARKET_TYPE = keccak256(abi.encode("basic-v1"));
81 | |
82 | | uint256 internal MAX_POOL_AMOUNT_WETH = 1_000_000_000e18;
83 | | uint256 internal MAX_POOL_AMOUNT_USDC = 1_000_000_000e30;
84 | | uint256 internal MAX_POOL_AMOUNT_USDT = 1_000_000_000e30;
85 | | uint internal MAX_POOL_AMOUNT_WBTC = 1_000_000_000e18;
86 | |
87 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_WETH = 1_000_000_000_000_000e30;
88 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_WBTC = 1_000_000_000_000_000e30;
89 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_USDC = 1_000_000_000_000_000e30;
90 | |
91 | | uint256 internal MIN_COLLATERAL_FACTOR = 1e28;
92 | | uint256 internal MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG =
93 | | 0;
94 | | uint256 internal MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT =
95 | | 0;
96 | | uint256 internal MAX_OPEN_INTEREST_LONG = 1000_000_000e30;
97 | | uint256 internal MAX_OPEN_INTEREST_SHORT = 1000_000_000e30;
98 | | uint256 internal RESERVE_FACTOR_LONG = 5e29;
99 | | uint256 internal RESERVE_FACTOR_SHORT = 5e29;
100 | | uint256 internal OPEN_INTEREST_RESERVE_FACTOR_LONG = 5e29;
101 | | uint256 internal OPEN_INTEREST_RESERVE_FACTOR_SHORT = 5e29;
102 | |
103 | | uint256 internal MAX_PNL_FACTOR_LONG = 5e29;
104 | | uint256 internal MAX_PNL_FACTOR_SHORT = 5e29;
105 | | uint256 internal MAX_PNL_FACTOR_FOR_TRADERS_LONG = 5e29;
106 | | uint256 internal MAX_PNL_FACTOR_FOR_TRADERS_SHORT = 5e29;
107 | | uint256 internal MAX_PNL_FACTOR_FOR_ADL_LONG = 45e28;
108 | | uint256 internal MAX_PNL_FACTOR_FOR_ADL_SHORT = 45e28;
109 | | uint256 internal MIN_PNL_FACTOR_AFTER_ADL_LONG = 40e28;
110 | | uint256 internal MIN_PNL_FACTOR_AFTER_ADL_SHORT = 40e28;
111 | | uint256 internal MAX_PNL_FACTOR_FOR_DEPOSITS_LONG = 60e28;
112 | | uint256 internal MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT = 60e28; //0.6
113 | | uint256 internal MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG = 30e28;
114 | | uint256 internal MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT = 30e28;
115 | | uint256 internal MARKET_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000;
116 | | uint256 internal MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = 1e28;
117 | | uint256 internal POSITION_IMPACT_FACTOR_POSITIVE = 2e28;
118 | | uint256 internal POSITION_IMPACT_FACTOR_NEGATIVE = 2e28;
119 | |
120 | | uint256 internal SWAP_FEE_FACTOR_POSITIVE_IMPACT = 5e26; //0.05%
121 | | uint256 internal SWAP_FEE_FACTOR_NEGATIVE_IMPACT = 7e26; //0.07%
122 | | uint256 internal SWAP_FEE_FACTOR_POSITIVE_IMPACT_SINGLE_TOKEN = 5e26; //0.05%
123 | | uint256 internal SWAP_FEE_FACTOR_NEGATIVE_IMPACT_SINGLE_TOKEN = 7e26; //0.07%
124 | | uint256 internal ATOMIC_SWAP_FEE_FACTOR = 2e28; //2%
125 | |
126 | | //--- funding
127 | |
128 | | uint256 internal FUNDING_FACTOR = 1e25;
129 | | uint256 internal FUNDING_EXPONENT_FACTOR = 1e30;
130 | |
131 | | uint256 internal THRESHOLD_FOR_STABLE_FUNDING = 0; // 5e28;
132 | | uint256 internal THRESHOLD_FOR_DECREASE_FUNDING = 0; //3e28;
133 | | uint256 internal FUNDING_INCREASE_FACTOR_PER_SECOND = 0; // 1e24;
134 | | uint256 internal FUNDING_DECREASE_FACTOR_PER_SECOND = 0; //2e22;
135 | | uint256 internal MIN_FUNDING_FACTOR_PER_SECOND = 1e25; //3e20
136 | | uint256 internal MAX_FUNDING_FACTOR_PER_SECOND = 1e30; //1e30;
137 | |
138 | | //--- v2.1 remediation
139 | |
140 | | uint256 internal EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = 1_000_000;
141 | | uint256 internal MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS =
142 | | 5_000_000;
143 | |
144 | | //---- GAMMA
145 | | uint256 internal ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = 0;
146 | | }
147 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzSetup.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/FuzzActors.sol";
6 | |
7 | | contract FuzzSetup is FuzzActors {
8 | | function deployment(address deployerContract) internal {
9 | | /**
10 | | * 0_0 *
11 | | * --- Deploying libraries using cryticArgs in fuzzer config ---
12 | | *
13 | | * --- DEPLOYING CONTRACTS ---
14 | | */
15 | |
16 | | //Role
17 | | //for foundry
18 | | DEPLOYER = deployerContract;
19 | |
20 | | roleStore = new RoleStore();
21 | | roleStore.grantRole(FOUNDRY_INITIAL_ADDRESS, Role.ROLE_ADMIN); //going from contract to EOA
22 | | roleStore.grantRole(DEPLOYER, Role.ROLE_ADMIN); //going from contract to EOA
23 | | roleStore.grantRole(HEVM_INITIAL_ADDRESS, Role.ROLE_ADMIN); //going from contract to EOA
24 | |
25 | | /**
26 | | * 0_0 *
27 | | * --- Config for roles ---
28 | | */
29 | |
30 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.CONTROLLER);
31 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.ORDER_KEEPER);
32 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.ADL_KEEPER);
33 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.LIQUIDATION_KEEPER);
34 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.MARKET_KEEPER);
35 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.FROZEN_ORDER_KEEPER);
36 | |
37 | | _roleChangingCall(
38 | | HEVM_INITIAL_ADDRESS,
39 | | HEVM_INITIAL_ADDRESS,
40 | | Role.CONTROLLER
41 | | ); //To avoid unnesessary prank calls
42 | | _roleChangingCall(
43 | | HEVM_INITIAL_ADDRESS,
44 | | HEVM_INITIAL_ADDRESS,
45 | | Role.ORDER_KEEPER
46 | | );
47 | | _roleChangingCall(
48 | | HEVM_INITIAL_ADDRESS,
49 | | HEVM_INITIAL_ADDRESS,
50 | | Role.ADL_KEEPER
51 | | );
52 | | _roleChangingCall(
53 | | HEVM_INITIAL_ADDRESS,
54 | | HEVM_INITIAL_ADDRESS,
55 | | Role.LIQUIDATION_KEEPER
56 | | );
57 | | _roleChangingCall(
58 | | HEVM_INITIAL_ADDRESS,
59 | | HEVM_INITIAL_ADDRESS,
60 | | Role.MARKET_KEEPER
61 | | );
62 | | _roleChangingCall(
63 | | HEVM_INITIAL_ADDRESS,
64 | | HEVM_INITIAL_ADDRESS,
65 | | Role.FROZEN_ORDER_KEEPER
66 | | );
67 | |
68 | | /**
69 | | * 0_0 *
70 | | * --- Deploy and mock tokens ---
71 | | */
72 | | dataStore = new DataStore(roleStore);
73 | |
74 | | WETH = new WNT();
75 | | // vm.label(address(WETH), "WETH");
76 | |
77 | | WBTC = new MintableToken("Wrapped Bitcoin", "WBTC", 8);
78 | | // vm.label(address(WBTC), "WBTC");
79 | |
80 | | USDC = new MintableToken("USD Circle", "USDC", 6);
81 | | // vm.label(address(USDC), "USDC");
82 | |
83 | | USDT = new MintableToken("USD Tether", "USDT", 6);
84 | | // vm.label(address(USDT), "USDT");
85 | |
86 | | /**
87 | | * 0_0 *
88 | | * --- Configure Data Store ---
89 | | */
90 | | _setUintDataStoreCall(
91 | | DEPLOYER,
92 | | "TOKEN_TRANSFER_GAS_LIMIT",
93 | | WETH_TOKEN_TRANSFER_GAS_LIMIT,
94 | | address(WETH)
95 | | );
96 | | _setUintDataStoreCall(
97 | | DEPLOYER,
98 | | "TOKEN_TRANSFER_GAS_LIMIT",
99 | | WBTC_TOKEN_TRANSFER_GAS_LIMIT,
100 | | address(WBTC)
101 | | );
102 | | _setUintDataStoreCall(
103 | | DEPLOYER,
104 | | "TOKEN_TRANSFER_GAS_LIMIT",
105 | | USDC_TOKEN_TRANSFER_GAS_LIMIT,
106 | | address(USDC)
107 | | );
108 | | _setUintDataStoreCall(
109 | | DEPLOYER,
110 | | "TOKEN_TRANSFER_GAS_LIMIT",
111 | | USDT_TOKEN_TRANSFER_GAS_LIMIT,
112 | | address(USDT)
113 | | );
114 | |
115 | | _setAddressDataStoreCall(DEPLOYER, "WNT", address(WETH), address(0));
116 | | _setAddressDataStoreCall(
117 | | DEPLOYER,
118 | | "FEE_RECEIVER",
119 | | address(0),
120 | | address(0)
121 | | );
122 | | _setAddressDataStoreCall(
123 | | DEPLOYER,
124 | | "HOLDING_ADDRESS",
125 | | address(0),
126 | | address(0)
127 | | );
128 | |
129 | | _setUintDataStoreCall(
130 | | DEPLOYER,
131 | | "MAX_UI_FEE_FACTOR",
132 | | MAX_UI_FEE_FACTOR,
133 | | address(0)
134 | | );
135 | | _setUintDataStoreCall(
136 | | DEPLOYER,
137 | | "MAX_AUTO_CANCEL_ORDERS",
138 | | MAX_AUTO_CANCEL_ORDERS,
139 | | address(0)
140 | | );
141 | | _setUintDataStoreCall(
142 | | DEPLOYER,
143 | | "MIN_HANDLE_EXECUTION_ERROR_GAS",
144 | | MIN_HANDLE_EXECUTION_ERROR_GAS,
145 | | address(0)
146 | | );
147 | | _setUintDataStoreCall(
148 | | DEPLOYER,
149 | | "MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD",
150 | | MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD,
151 | | address(0)
152 | | );
153 | |
154 | | _setUintDataStoreCall(
155 | | DEPLOYER,
156 | | "MIN_ADDITIONAL_GAS_FOR_EXECUTION",
157 | | MIN_ADDITIONAL_GAS_FOR_EXECUTION,
158 | | address(0)
159 | | );
160 | | _setUintDataStoreCall(
161 | | DEPLOYER,
162 | | "MAX_CALLBACK_GAS_LIMIT",
163 | | MAX_CALLBACK_GAS_LIMIT,
164 | | address(0)
165 | | );
166 | | _setUintDataStoreCall(
167 | | DEPLOYER,
168 | | "MAX_SWAP_PATH_LENGTH",
169 | | MAX_SWAP_PATH_LENGTH,
170 | | address(0)
171 | | );
172 | | _setUintDataStoreCall(
173 | | DEPLOYER,
174 | | "MIN_COLLATERAL_USD",
175 | | MIN_COLLATERAL_USD,
176 | | address(0)
177 | | );
178 | | _setUintDataStoreCall(
179 | | DEPLOYER,
180 | | "MIN_POSITION_SIZE_USD",
181 | | MIN_POSITION_SIZE_USD,
182 | | address(0)
183 | | );
184 | | _setUintDataStoreCall(
185 | | DEPLOYER,
186 | | "SWAP_FEE_RECEIVER_FACTOR",
187 | | SWAP_FEE_RECEIVER_FACTOR,
188 | | address(0)
189 | | );
190 | | _setUintDataStoreCall(
191 | | DEPLOYER,
192 | | "POSITION_FEE_RECEIVER_FACTOR",
193 | | POSITION_FEE_RECEIVER_FACTOR,
194 | | address(0)
195 | | );
196 | | _setUintDataStoreCall(
197 | | DEPLOYER,
198 | | "CLAIMABLE_COLLATERAL_TIME_DIVISOR",
199 | | CLAIMABLE_COLLATERAL_TIME_DIVISOR,
200 | | address(0)
201 | | );
202 | | _setUintWithBoolDataStoreCall(
203 | | DEPLOYER,
204 | | "DEPOSIT_GAS_LIMIT",
205 | | DEPOSIT_GAS_LIMIT,
206 | | true
207 | | );
208 | | _setUintWithBoolDataStoreCall(
209 | | DEPLOYER,
210 | | "DEPOSIT_GAS_LIMIT",
211 | | DEPOSIT_GAS_LIMIT,
212 | | false
213 | | );
214 | | _setUintDataStoreCall(
215 | | DEPLOYER,
216 | | "WITHDRAWAL_GAS_LIMIT",
217 | | WITHDRAWAL_GAS_LIMIT,
218 | | address(0)
219 | | );
220 | | _setUintDataStoreCall(
221 | | DEPLOYER,
222 | | "SINGLE_SWAP_GAS_LIMIT",
223 | | SINGLE_SWAP_GAS_LIMIT,
224 | | address(0)
225 | | );
226 | | _setUintDataStoreCall(
227 | | DEPLOYER,
228 | | "INCREASE_ORDER_GAS_LIMIT",
229 | | INCREASE_ORDER_GAS_LIMIT,
230 | | address(0)
231 | | );
232 | | _setUintDataStoreCall(
233 | | DEPLOYER,
234 | | "DECREASE_ORDER_GAS_LIMIT",
235 | | DECREASE_ORDER_GAS_LIMIT,
236 | | address(0)
237 | | );
238 | | _setUintDataStoreCall(
239 | | DEPLOYER,
240 | | "SWAP_ORDER_GAS_LIMIT",
241 | | SWAP_ORDER_GAS_LIMIT,
242 | | address(0)
243 | | );
244 | | _setUintDataStoreCall(
245 | | DEPLOYER,
246 | | "NATIVE_TOKEN_TRANSFER_GAS_LIMIT",
247 | | NATIVE_TOKEN_TRANSFER_GAS_LIMIT,
248 | | address(0)
249 | | );
250 | | _setUintDataStoreCall(
251 | | DEPLOYER,
252 | | "ESTIMATED_GAS_FEE_BASE_AMOUNT",
253 | | ESTIMATED_GAS_FEE_BASE_AMOUNT,
254 | | address(0)
255 | | );
256 | | _setUintDataStoreCall(
257 | | DEPLOYER,
258 | | "ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1",
259 | | ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1,
260 | | address(0)
261 | | );
262 | | _setUintDataStoreCall(
263 | | DEPLOYER,
264 | | "EXECUTION_GAS_FEE_MULTIPLIER_FACTOR",
265 | | EXECUTION_GAS_FEE_MULTIPLIER_FACTOR,
266 | | address(0)
267 | | );
268 | |
269 | | _setUintDataStoreCall(
270 | | DEPLOYER,
271 | | "REFUND_EXECUTION_FEE_GAS_LIMIT",
272 | | REFUND_EXECUTION_FEE_GAS_LIMIT,
273 | | address(0)
274 | | );
275 | |
276 | | _setUintDataStoreCall(
277 | | DEPLOYER,
278 | | "EXECUTION_GAS_FEE_PER_ORACLE_PRICE",
279 | | EXECUTION_GAS_FEE_PER_ORACLE_PRICE,
280 | | address(0)
281 | | );
282 | |
283 | | _setBoolDataStoreCall(
284 | | DEPLOYER,
285 | | "SKIP_BORROWING_FEE_FOR_SMALLER_SIDE",
286 | | SKIP_BORROWING_FEE_FOR_SMALLER_SIDE,
287 | | address(0)
288 | | );
289 | | _setUintDataStoreCall(
290 | | DEPLOYER,
291 | | "REQUEST_EXPIRATION_TIME",
292 | | REQUEST_EXPIRATION_TIME,
293 | | address(0)
294 | | );
295 | | _setUintDataStoreCall(
296 | | DEPLOYER,
297 | | "ESTIMATED_GAS_FEE_PER_ORACLE_PRICE",
298 | | ESTIMATED_GAS_FEE_PER_ORACLE_PRICE,
299 | | address(0)
300 | | );
301 | | /**
302 | | * 0_0 *
303 | | * --- Setup Timelock Controller ---
304 | | */
305 | | govTimelockController = new GovTimelockController(
306 | | "GovTimelockController", //name
307 | | 5 * 24 * 60 * 60, // minDelay
308 | | USERS, //proposer
309 | | USERS, //executor
310 | | DEPLOYER //admin
311 | | );
312 | |
313 | | bytes32 PROPOSER_ROLE = govTimelockController.PROPOSER_ROLE();
314 | | vm.prank(DEPLOYER);
315 | | govTimelockController.grantRole(
316 | | PROPOSER_ROLE,
317 | | address(protocolGovernor)
318 | | );
319 | |
320 | | bytes32 CANCELLER_ROLE = govTimelockController.CANCELLER_ROLE();
321 | | vm.prank(DEPLOYER);
322 | | govTimelockController.grantRole(
323 | | CANCELLER_ROLE,
324 | | address(protocolGovernor)
325 | | );
326 | |
327 | | bytes32 EXECUTOR_ROLE = govTimelockController.EXECUTOR_ROLE();
328 | | vm.prank(DEPLOYER);
329 | | govTimelockController.grantRole(
330 | | EXECUTOR_ROLE,
331 | | address(protocolGovernor)
332 | | );
333 | |
334 | | // bytes32 TIMELOCK_ADMIN_ROLE = govTimelockController.TIMELOCK_ADMIN_ROLE();
335 | | // vm.prank(DEPLOYER);
336 | | // govTimelockController.revokeRole(TIMELOCK_ADMIN_ROLE, DEPLOYER);
337 | |
338 | | /**
339 | | * 0_0 *
340 | | * --- Deploy gov contracts ---
341 | | */
342 | | govToken = new GovToken(
343 | | roleStore,
344 | | "GMX DAO", // name
345 | | "GMX_DAO", // symbol
346 | | 18
347 | | ); // decimals
348 | |
349 | | //@dev all values from ProtocolGovenor.ts test file,
350 | | //@dev test file have much smaller proposalTreshold
351 | | /**
352 | | * values from deployProtocolGovernor.ts
353 | | * return [
354 | | * dependencyContracts.GovToken.address, // token
355 | | * dependencyContracts.GovTimelockController.address, // timelock
356 | | * "GMX Governor", // name
357 | | * "v2.0", // version
358 | | * 24 * 60 * 60, // votingDelay
359 | | * 5 * 24 * 60 * 60, // votingPeriod
360 | | * expandDecimals(30_000, 18), // proposalThreshold
361 | | * 3, // quorumNumeratorValue
362 | | * ];
363 | | */
364 | | protocolGovernor = new ProtocolGovernor(
365 | | govToken,
366 | | govTimelockController, // timelock
367 | | "Governor", // name
368 | | "v1", // version
369 | | 24 * 60 * 60, // votingDelay
370 | | 6 * 24 * 60 * 60, // votingPeriod
371 | | 50_000, // proposalThreshold
372 | | 4 // quorumNumeratorValue);
373 | | );
374 | |
375 | | eventEmitter = new EventEmitter(roleStore);
376 | |
377 | | /**
378 | | * 0_0 *
379 | | * --- Oracle setup ---
380 | | */
381 | | oracleStore = new OracleStore(roleStore, eventEmitter);
382 | | _roleChangingCall(DEPLOYER, address(oracleStore), Role.CONTROLLER);
383 | |
384 | | _oracleAddSignerCall(DEPLOYER, USER4);
385 | | _oracleAddSignerCall(DEPLOYER, USER5);
386 | | _oracleAddSignerCall(DEPLOYER, USER6);
387 | | _oracleAddSignerCall(DEPLOYER, USER7);
388 | | _oracleAddSignerCall(DEPLOYER, USER8);
389 | | _oracleAddSignerCall(DEPLOYER, USER9);
390 | | _oracleAddSignerCall(DEPLOYER, USER10);
391 | | _oracleAddSignerCall(DEPLOYER, USER11);
392 | | _oracleAddSignerCall(DEPLOYER, USER12);
393 | | _oracleAddSignerCall(DEPLOYER, USER13);
394 | |
395 | | _setUintDataStoreCall(
396 | | DEPLOYER,
397 | | "MIN_ORACLE_SIGNERS",
398 | | MIN_ORACLE_SIGNERS,
399 | | address(0)
400 | | );
401 | |
402 | | USDCPriceFeed = new MockPriceFeed();
403 | | USDCPriceFeed.setAnswer(USDC_INIT_PRICE);
404 | |
405 | | USDTPriceFeed = new MockPriceFeed();
406 | | USDTPriceFeed.setAnswer(USDT_INIT_PRICE);
407 | |
408 | | gmOracleProvider = new GmOracleProvider(
409 | | roleStore,
410 | | dataStore,
411 | | oracleStore
412 | | );
413 | |
414 | | chainlinkMock = new ChainlinkMock();
415 | |
416 | | _setBoolDataStoreCall(
417 | | DEPLOYER,
418 | | "IS_ORACLE_PROVIDER_ENABLED",
419 | | IS_ORACLE_PROVIDER_ENABLED,
420 | | address(0)
421 | | );
422 | |
423 | | mockDataStreamVerifier = new MockDataStreamVerifier();
424 | | chainlinkPriceFeedProvider = new ChainlinkPriceFeedProvider(dataStore);
425 | |
426 | | _setBoolDataStoreCall(
427 | | DEPLOYER,
428 | | "IS_ORACLE_PROVIDER_ENABLED",
429 | | IS_ORACLE_PROVIDER_ENABLED,
430 | | address(chainlinkPriceFeedProvider)
431 | | );
432 | | _setBoolDataStoreCall(
433 | | DEPLOYER,
434 | | "IS_ATOMIC_ORACLE_PROVIDER",
435 | | IS_ATOMIC_ORACLE_PROVIDER,
436 | | address(chainlinkPriceFeedProvider)
437 | | );
438 | |
439 | | _setBoolDataStoreCall(
440 | | DEPLOYER,
441 | | "IS_ORACLE_PROVIDER_ENABLED",
442 | | IS_ORACLE_PROVIDER_ENABLED,
443 | | address(chainlinkMock)
444 | | );
445 | | _setBoolDataStoreCall(
446 | | DEPLOYER,
447 | | "IS_ATOMIC_ORACLE_PROVIDER",
448 | | IS_ATOMIC_ORACLE_PROVIDER,
449 | | address(chainlinkMock)
450 | | );
451 | |
452 | | oracle = new Oracle(
453 | | roleStore,
454 | | dataStore,
455 | | eventEmitter,
456 | | AggregatorV2V3Interface(address(0)) //sequencer uptime feed AggregatorV2V3Interface
457 | | );
458 | |
459 | | _setUintDataStoreCall(
460 | | DEPLOYER,
461 | | "MIN_ORACLE_BLOCK_CONFIRMATIONS",
462 | | MIN_ORACLE_BLOCK_CONFIRMATIONS,
463 | | address(0)
464 | | );
465 | | _setUintDataStoreCall(
466 | | DEPLOYER,
467 | | "MAX_ORACLE_TIMESTAMP_RANGE",
468 | | MAX_ORACLE_TIMESTAMP_RANGE,
469 | | address(0)
470 | | );
471 | | _setUintDataStoreCall(
472 | | DEPLOYER,
473 | | "MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR",
474 | | MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR,
475 | | address(0)
476 | | );
477 | | _setAddressDataStoreCall(
478 | | DEPLOYER,
479 | | "CHAINLINK_PAYMENT_TOKEN",
480 | | CHAINLINK_PAYMENT_TOKEN,
481 | | address(0)
482 | | );
483 | |
484 | | _roleChangingCall(DEPLOYER, address(oracle), Role.CONTROLLER);
485 | |
486 | | chainlinkDataStreamProvider = new ChainlinkDataStreamProvider(
487 | | dataStore,
488 | | address(oracle),
489 | | mockDataStreamVerifier
490 | | );
491 | |
492 | | _setBoolDataStoreCall(
493 | | DEPLOYER,
494 | | "IS_ORACLE_PROVIDER_ENABLED",
495 | | IS_ORACLE_PROVIDER_ENABLED,
496 | | address(chainlinkDataStreamProvider)
497 | | );
498 | |
499 | | _setBytes32DataStoreCall(
500 | | DEPLOYER,
501 | | "ORACLE_TYPE",
502 | | address(USDC),
503 | | ORACLE_TYPE_DEFAULT
504 | | );
505 | | _setAddressDataStoreCall(
506 | | DEPLOYER,
507 | | "ORACLE_PROVIDER_FOR_TOKEN",
508 | | address(gmOracleProvider),
509 | | address(USDC)
510 | | ); //KEY is a string + USDC(added address for a key)
511 | | _setAddressDataStoreCall(
512 | | DEPLOYER,
513 | | "PRICE_FEED",
514 | | address(USDCPriceFeed),
515 | | address(0)
516 | | );
517 | | _setUintDataStoreCall(
518 | | DEPLOYER,
519 | | "PRICE_FEED_MULTIPLIER",
520 | | PRICE_FEED_MULTIPLIER,
521 | | address(USDC)
522 | | );
523 | | _setUintDataStoreCall(
524 | | DEPLOYER,
525 | | "PRICE_FEED_HEARTBEAT_DURATION",
526 | | PRICE_FEED_HEARTBEAT_DURATION,
527 | | address(USDC)
528 | | );
529 | |
530 | | _setBytes32DataStoreCall(
531 | | DEPLOYER,
532 | | "ORACLE_TYPE",
533 | | address(USDT),
534 | | ORACLE_TYPE_DEFAULT
535 | | );
536 | | _setAddressDataStoreCall(
537 | | DEPLOYER,
538 | | "ORACLE_PROVIDER_FOR_TOKEN",
539 | | address(gmOracleProvider),
540 | | address(USDT)
541 | | );
542 | | _setAddressDataStoreCall(
543 | | DEPLOYER,
544 | | "PRICE_FEED",
545 | | address(USDTPriceFeed),
546 | | address(0)
547 | | );
548 | | _setUintDataStoreCall(
549 | | DEPLOYER,
550 | | "PRICE_FEED_MULTIPLIER",
551 | | PRICE_FEED_MULTIPLIER,
552 | | address(USDT)
553 | | );
554 | | _setUintDataStoreCall(
555 | | DEPLOYER,
556 | | "PRICE_FEED_HEARTBEAT_DURATION",
557 | | PRICE_FEED_HEARTBEAT_DURATION,
558 | | address(USDT)
559 | | );
560 | |
561 | | _setBytes32DataStoreCall(
562 | | DEPLOYER,
563 | | "ORACLE_TYPE",
564 | | address(WETH),
565 | | ORACLE_TYPE_DEFAULT
566 | | );
567 | | _setAddressDataStoreCall(
568 | | DEPLOYER,
569 | | "ORACLE_PROVIDER_FOR_TOKEN",
570 | | address(gmOracleProvider),
571 | | address(WETH)
572 | | );
573 | |
574 | | _setBytes32DataStoreCall(
575 | | DEPLOYER,
576 | | "ORACLE_TYPE",
577 | | address(WBTC),
578 | | ORACLE_TYPE_DEFAULT
579 | | );
580 | | _setAddressDataStoreCall(
581 | | DEPLOYER,
582 | | "ORACLE_PROVIDER_FOR_TOKEN",
583 | | address(gmOracleProvider),
584 | | address(WBTC)
585 | | );
586 | |
587 | | _setBytes32DataStoreCall(
588 | | DEPLOYER,
589 | | "ORACLE_TYPE",
590 | | address(SOL),
591 | | ORACLE_TYPE_DEFAULT
592 | | ); //synthetic address
593 | | _setAddressDataStoreCall(
594 | | DEPLOYER,
595 | | "ORACLE_PROVIDER_FOR_TOKEN",
596 | | address(gmOracleProvider),
597 | | address(SOL)
598 | | );
599 | |
600 | | /**
601 | | * 0_0 *
602 | | * --- Adding custom ChainLink mock---
603 | | */
604 | | _setBytes32DataStoreCall(
605 | | DEPLOYER,
606 | | "ORACLE_TYPE",
607 | | address(USDT),
608 | | ORACLE_TYPE_DEFAULT
609 | | );
610 | | _setAddressDataStoreCall(
611 | | DEPLOYER,
612 | | "ORACLE_PROVIDER_FOR_TOKEN",
613 | | address(chainlinkMock),
614 | | address(USDT)
615 | | );
616 | |
617 | | _setBytes32DataStoreCall(
618 | | DEPLOYER,
619 | | "ORACLE_TYPE",
620 | | address(USDC),
621 | | ORACLE_TYPE_DEFAULT
622 | | );
623 | | _setAddressDataStoreCall(
624 | | DEPLOYER,
625 | | "ORACLE_PROVIDER_FOR_TOKEN",
626 | | address(chainlinkMock),
627 | | address(USDC)
628 | | );
629 | | _setBytes32DataStoreCall(
630 | | DEPLOYER,
631 | | "ORACLE_TYPE",
632 | | address(WETH),
633 | | ORACLE_TYPE_DEFAULT
634 | | );
635 | | _setAddressDataStoreCall(
636 | | DEPLOYER,
637 | | "ORACLE_PROVIDER_FOR_TOKEN",
638 | | address(chainlinkMock),
639 | | address(WETH)
640 | | );
641 | |
642 | | _setBytes32DataStoreCall(
643 | | DEPLOYER,
644 | | "ORACLE_TYPE",
645 | | address(WBTC),
646 | | ORACLE_TYPE_DEFAULT
647 | | );
648 | | _setAddressDataStoreCall(
649 | | DEPLOYER,
650 | | "ORACLE_PROVIDER_FOR_TOKEN",
651 | | address(chainlinkMock),
652 | | address(WBTC)
653 | | );
654 | |
655 | | _setBytes32DataStoreCall(
656 | | DEPLOYER,
657 | | "ORACLE_TYPE",
658 | | address(SOL),
659 | | ORACLE_TYPE_DEFAULT
660 | | ); //synthetic address
661 | | _setAddressDataStoreCall(
662 | | DEPLOYER,
663 | | "ORACLE_PROVIDER_FOR_TOKEN",
664 | | address(chainlinkMock),
665 | | address(SOL)
666 | | );
667 | |
668 | | /**
669 | | * 0_0 *
670 | | * --- Deploy order related contracts ---
671 | | */
672 | | orderVault = new OrderVault(roleStore, dataStore);
673 | | swapHandler = new SwapHandler(roleStore);
674 | | _roleChangingCall(DEPLOYER, address(swapHandler), Role.CONTROLLER);
675 | |
676 | | referralStorage = new ReferralStorage();
677 | | referralStorage.setTier(0, 1000, 5000);
678 | | referralStorage.setTier(1, 2000, 5000);
679 | | referralStorage.setTier(0, 2500, 4000);
680 | |
681 | | adlHandler = new AdlHandler(
682 | | roleStore,
683 | | dataStore,
684 | | eventEmitter,
685 | | oracle,
686 | | orderVault,
687 | | swapHandler,
688 | | referralStorage
689 | | );
690 | | _roleChangingCall(DEPLOYER, address(adlHandler), Role.CONTROLLER);
691 | |
692 | | marketFactory = new MarketFactory(roleStore, dataStore, eventEmitter);
693 | | _roleChangingCall(DEPLOYER, address(marketFactory), Role.CONTROLLER);
694 | |
695 | | config = new Config(roleStore, dataStore, eventEmitter);
696 | | _roleChangingCall(DEPLOYER, address(config), Role.CONTROLLER);
697 | |
698 | | /**
699 | | * 0_0 *
700 | | * --- Deploy deposit related contracts ---
701 | | */
702 | | depositVault = new DepositVault(roleStore, dataStore);
703 | | depositHandler = new DepositHandler(
704 | | roleStore,
705 | | dataStore,
706 | | eventEmitter,
707 | | oracle,
708 | | depositVault
709 | | );
710 | | _roleChangingCall(DEPLOYER, address(depositHandler), Role.CONTROLLER);
711 | |
712 | | router = new Router(roleStore);
713 | |
714 | | /**
715 | | * 0_0 *
716 | | * --- Deploy withdrawal related contracts ---
717 | | */
718 | | withdrawalVault = new WithdrawalVault(roleStore, dataStore);
719 | | withdrawalHandler = new WithdrawalHandler(
720 | | roleStore,
721 | | dataStore,
722 | | eventEmitter,
723 | | oracle,
724 | | withdrawalVault
725 | | );
726 | | _roleChangingCall(
727 | | DEPLOYER,
728 | | address(withdrawalHandler),
729 | | Role.CONTROLLER
730 | | );
731 | |
732 | | /**
733 | | * 0_0 *
734 | | * --- Deploy shift related contracts ---
735 | | */
736 | | shiftVault = new ShiftVault(roleStore, dataStore);
737 | | shiftHandler = new ShiftHandler(
738 | | roleStore,
739 | | dataStore,
740 | | eventEmitter,
741 | | oracle,
742 | | shiftVault
743 | | );
744 | | _roleChangingCall(DEPLOYER, address(shiftHandler), Role.CONTROLLER);
745 | |
746 | | orderHandler = new OrderHandler(
747 | | roleStore,
748 | | dataStore,
749 | | eventEmitter,
750 | | oracle,
751 | | orderVault,
752 | | swapHandler,
753 | | referralStorage
754 | | );
755 | |
756 | | referralStorage.setHandler(address(orderHandler), true);
757 | |
758 | | _roleChangingCall(DEPLOYER, address(orderHandler), Role.CONTROLLER);
759 | |
760 | | externalHandler = new ExternalHandler();
761 | |
762 | | exchangeRouter = new ExchangeRouter(
763 | | router,
764 | | roleStore,
765 | | dataStore,
766 | | eventEmitter,
767 | | depositHandler,
768 | | withdrawalHandler,
769 | | shiftHandler,
770 | | orderHandler,
771 | | externalHandler
772 | | );
773 | |
774 | | _roleChangingCall(DEPLOYER, address(exchangeRouter), Role.CONTROLLER);
775 | | _roleChangingCall(
776 | | DEPLOYER,
777 | | address(exchangeRouter),
778 | | Role.ROUTER_PLUGIN
779 | | );
780 | |
781 | | feeHandler = new FeeHandler(roleStore, dataStore, eventEmitter);
782 | | _roleChangingCall(DEPLOYER, address(feeHandler), Role.CONTROLLER);
783 | |
784 | | liquidationHandler = new LiquidationHandler(
785 | | roleStore,
786 | | dataStore,
787 | | eventEmitter,
788 | | oracle,
789 | | orderVault,
790 | | swapHandler,
791 | | referralStorage
792 | | );
793 | | _roleChangingCall(
794 | | DEPLOYER,
795 | | address(liquidationHandler),
796 | | Role.CONTROLLER
797 | | );
798 | |
799 | | //Simple price feed
800 | | mockPriceFeed = new MockPriceFeed();
801 | | multicall3 = new Multicall3();
802 | |
803 | | /**
804 | | * 0_0 *
805 | | * --- Deploy reader related contracts ---
806 | | */
807 | | subaccountRouter = new SubaccountRouter(
808 | | router,
809 | | roleStore,
810 | | dataStore,
811 | | eventEmitter,
812 | | orderHandler,
813 | | orderVault
814 | | );
815 | | _roleChangingCall(DEPLOYER, address(subaccountRouter), Role.CONTROLLER);
816 | | _roleChangingCall(
817 | | DEPLOYER,
818 | | address(subaccountRouter),
819 | | Role.ROUTER_PLUGIN
820 | | );
821 | |
822 | | timelock = new Timelock(
823 | | roleStore,
824 | | dataStore,
825 | | eventEmitter,
826 | | oracleStore,
827 | | 24 * 60 * 60 //timelockDelay
828 | | );
829 | | _roleChangingCall(DEPLOYER, address(timelock), Role.CONTROLLER);
830 | | _roleChangingCall(DEPLOYER, address(timelock), Role.ROLE_ADMIN);
831 | |
832 | | timestampInitializer = new TimestampInitializer(
833 | | roleStore,
834 | | dataStore,
835 | | eventEmitter
836 | | );
837 | | _roleChangingCall(
838 | | DEPLOYER,
839 | | address(timestampInitializer),
840 | | Role.CONTROLLER
841 | | );
842 | |
843 | | reader = new Reader();
844 | | }
845 | |
846 | | function marketsSetup() internal {
847 | | /**
848 | | * 0_0 *
849 | | * --- New markets, should include all supported combinations ---
850 | | */
851 | | market_WETH_WETH_USDC = marketFactory
852 | | .createMarket(
853 | | address(WETH),
854 | | address(WETH),
855 | | address(USDC),
856 | | DEFAULT_MARKET_TYPE
857 | | )
858 | | .marketToken;
859 | | // vm.label(address(market_WETH_WETH_USDC), "market_WETH_WETH_USDC");
860 | |
861 | | market_WETH_WETH_USDT = marketFactory
862 | | .createMarket(
863 | | address(WETH),
864 | | address(WETH),
865 | | address(USDT),
866 | | DEFAULT_MARKET_TYPE
867 | | )
868 | | .marketToken;
869 | | // vm.label(address(market_WETH_WETH_USDT), "market_WETH_WETH_USDT");
870 | |
871 | | market_0_WETH_USDC = marketFactory
872 | | .createMarket(
873 | | address(0),
874 | | address(WETH),
875 | | address(USDC),
876 | | DEFAULT_MARKET_TYPE
877 | | )
878 | | .marketToken;
879 | | // vm.label(address(market_0_WETH_USDC), "market_0_WETH_USDC");
880 | |
881 | | market_WBTC_WBTC_USDC = marketFactory
882 | | .createMarket(
883 | | address(WBTC),
884 | | address(WBTC),
885 | | address(USDC),
886 | | DEFAULT_MARKET_TYPE
887 | | )
888 | | .marketToken;
889 | | // vm.label(address(market_WBTC_WBTC_USDC), "market_WBTC_WBTC_USDC");
890 | |
891 | | /**
892 | | * 0_0 *
893 | | * --- Config for market_WETH_WETH_USDC ---
894 | | */
895 | | _setUintDataStoreCall(
896 | | DEPLOYER,
897 | | "MAX_POOL_AMOUNT",
898 | | MAX_POOL_AMOUNT_WETH,
899 | | market_WETH_WETH_USDC,
900 | | address(WETH)
901 | | );
902 | | _setUintDataStoreCall(
903 | | DEPLOYER,
904 | | "MAX_POOL_AMOUNT",
905 | | MAX_POOL_AMOUNT_USDC,
906 | | market_WETH_WETH_USDC,
907 | | address(USDC)
908 | | );
909 | | _setUintDataStoreCall(
910 | | DEPLOYER,
911 | | "MAX_POOL_USD_FOR_DEPOSIT",
912 | | MAX_POOL_USD_FOR_DEPOSIT_WETH,
913 | | market_WETH_WETH_USDC,
914 | | address(WETH)
915 | | );
916 | | _setUintDataStoreCall(
917 | | DEPLOYER,
918 | | "MAX_POOL_USD_FOR_DEPOSIT",
919 | | MAX_POOL_USD_FOR_DEPOSIT_USDC,
920 | | market_WETH_WETH_USDC,
921 | | address(USDC)
922 | | );
923 | | _setUintDataStoreCall(
924 | | DEPLOYER,
925 | | "MIN_COLLATERAL_FACTOR",
926 | | MIN_COLLATERAL_FACTOR,
927 | | market_WETH_WETH_USDC
928 | | );
929 | | _setUintDataStoreCall(
930 | | DEPLOYER,
931 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
932 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG,
933 | | market_WETH_WETH_USDC,
934 | | true
935 | | );
936 | | _setUintDataStoreCall(
937 | | DEPLOYER,
938 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
939 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT,
940 | | market_WETH_WETH_USDC,
941 | | false
942 | | );
943 | | _setUintDataStoreCall(
944 | | DEPLOYER,
945 | | "MAX_OPEN_INTEREST",
946 | | MAX_OPEN_INTEREST_LONG,
947 | | market_WETH_WETH_USDC,
948 | | true
949 | | );
950 | | _setUintDataStoreCall(
951 | | DEPLOYER,
952 | | "MAX_OPEN_INTEREST",
953 | | MAX_OPEN_INTEREST_SHORT,
954 | | market_WETH_WETH_USDC,
955 | | false
956 | | );
957 | | _setUintDataStoreCall(
958 | | DEPLOYER,
959 | | "RESERVE_FACTOR",
960 | | RESERVE_FACTOR_LONG,
961 | | market_WETH_WETH_USDC,
962 | | true
963 | | );
964 | | _setUintDataStoreCall(
965 | | DEPLOYER,
966 | | "RESERVE_FACTOR",
967 | | RESERVE_FACTOR_SHORT,
968 | | market_WETH_WETH_USDC,
969 | | false
970 | | );
971 | | _setUintDataStoreCall(
972 | | DEPLOYER,
973 | | "OPEN_INTEREST_RESERVE_FACTOR",
974 | | OPEN_INTEREST_RESERVE_FACTOR_LONG,
975 | | market_WETH_WETH_USDC,
976 | | true
977 | | );
978 | | _setUintDataStoreCall(
979 | | DEPLOYER,
980 | | "OPEN_INTEREST_RESERVE_FACTOR",
981 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT,
982 | | market_WETH_WETH_USDC,
983 | | false
984 | | );
985 | |
986 | | _setUintDataStoreCall(
987 | | DEPLOYER,
988 | | "MAX_PNL_FACTOR",
989 | | "MAX_PNL_FACTOR_FOR_TRADERS",
990 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG,
991 | | market_WETH_WETH_USDC,
992 | | true
993 | | );
994 | | _setUintDataStoreCall(
995 | | DEPLOYER,
996 | | "MAX_PNL_FACTOR",
997 | | "MAX_PNL_FACTOR_FOR_TRADERS",
998 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT,
999 | | market_WETH_WETH_USDC,
1000 | | false
1001 | | );
1002 | | _setUintDataStoreCall(
1003 | | DEPLOYER,
1004 | | "MAX_PNL_FACTOR",
1005 | | "MAX_PNL_FACTOR_FOR_ADL",
1006 | | MAX_PNL_FACTOR_FOR_ADL_LONG,
1007 | | market_WETH_WETH_USDC,
1008 | | true
1009 | | );
1010 | | _setUintDataStoreCall(
1011 | | DEPLOYER,
1012 | | "MAX_PNL_FACTOR",
1013 | | "MAX_PNL_FACTOR_FOR_ADL",
1014 | | MAX_PNL_FACTOR_FOR_ADL_SHORT,
1015 | | market_WETH_WETH_USDC,
1016 | | false
1017 | | );
1018 | | _setUintDataStoreCall(
1019 | | DEPLOYER,
1020 | | "MIN_PNL_FACTOR_AFTER_ADL",
1021 | | MIN_PNL_FACTOR_AFTER_ADL_LONG,
1022 | | market_WETH_WETH_USDC,
1023 | | true
1024 | | );
1025 | | _setUintDataStoreCall(
1026 | | DEPLOYER,
1027 | | "MIN_PNL_FACTOR_AFTER_ADL",
1028 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT,
1029 | | market_WETH_WETH_USDC,
1030 | | false
1031 | | );
1032 | | _setUintDataStoreCall(
1033 | | DEPLOYER,
1034 | | "MAX_PNL_FACTOR",
1035 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1036 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG,
1037 | | market_WETH_WETH_USDC,
1038 | | true
1039 | | );
1040 | | _setUintDataStoreCall(
1041 | | DEPLOYER,
1042 | | "MAX_PNL_FACTOR",
1043 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1044 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT,
1045 | | market_WETH_WETH_USDC,
1046 | | false
1047 | | );
1048 | | _setUintDataStoreCall(
1049 | | DEPLOYER,
1050 | | "MAX_PNL_FACTOR",
1051 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1052 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG,
1053 | | market_WETH_WETH_USDC,
1054 | | true
1055 | | );
1056 | | _setUintDataStoreCall(
1057 | | DEPLOYER,
1058 | | "MAX_PNL_FACTOR",
1059 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1060 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT,
1061 | | market_WETH_WETH_USDC,
1062 | | false
1063 | | );
1064 | | _setUintDataStoreCall(
1065 | | DEPLOYER,
1066 | | "TOKEN_TRANSFER_GAS_LIMIT",
1067 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT,
1068 | | market_WETH_WETH_USDC
1069 | | );
1070 | | _setUintDataStoreCall(
1071 | | DEPLOYER,
1072 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS",
1073 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,
1074 | | market_WETH_WETH_USDC
1075 | | );
1076 | | _setUintDataStoreCall(
1077 | | DEPLOYER,
1078 | | "POSITION_IMPACT_FACTOR",
1079 | | POSITION_IMPACT_FACTOR_POSITIVE,
1080 | | market_WETH_WETH_USDC,
1081 | | true
1082 | | );
1083 | | _setUintDataStoreCall(
1084 | | DEPLOYER,
1085 | | "POSITION_IMPACT_FACTOR",
1086 | | POSITION_IMPACT_FACTOR_NEGATIVE,
1087 | | market_WETH_WETH_USDC,
1088 | | false
1089 | | );
1090 | |
1091 | | _setUintDataStoreCall(
1092 | | DEPLOYER,
1093 | | "SWAP_FEE_FACTOR",
1094 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT,
1095 | | market_WETH_WETH_USDC,
1096 | | true
1097 | | );
1098 | |
1099 | | _setUintDataStoreCall(
1100 | | DEPLOYER,
1101 | | "SWAP_FEE_FACTOR",
1102 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT,
1103 | | market_WETH_WETH_USDC,
1104 | | false
1105 | | );
1106 | |
1107 | | _setUintDataStoreCall(
1108 | | DEPLOYER,
1109 | | "ATOMIC_SWAP_FEE_FACTOR",
1110 | | ATOMIC_SWAP_FEE_FACTOR,
1111 | | market_WETH_WETH_USDC
1112 | | );
1113 | |
1114 | | _setUintDataStoreCall(
1115 | | DEPLOYER,
1116 | | "FUNDING_FACTOR",
1117 | | FUNDING_FACTOR,
1118 | | market_WETH_WETH_USDC
1119 | | );
1120 | |
1121 | | _setUintDataStoreCall(
1122 | | DEPLOYER,
1123 | | "FUNDING_EXPONENT_FACTOR",
1124 | | FUNDING_EXPONENT_FACTOR,
1125 | | market_WETH_WETH_USDC
1126 | | );
1127 | |
1128 | | _setUintDataStoreCall(
1129 | | DEPLOYER,
1130 | | "THRESHOLD_FOR_STABLE_FUNDING",
1131 | | THRESHOLD_FOR_STABLE_FUNDING,
1132 | | market_WETH_WETH_USDC
1133 | | );
1134 | |
1135 | | _setUintDataStoreCall(
1136 | | DEPLOYER,
1137 | | "THRESHOLD_FOR_DECREASE_FUNDING",
1138 | | THRESHOLD_FOR_DECREASE_FUNDING,
1139 | | market_WETH_WETH_USDC
1140 | | );
1141 | | _setUintDataStoreCall(
1142 | | DEPLOYER,
1143 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1144 | | FUNDING_INCREASE_FACTOR_PER_SECOND,
1145 | | market_WETH_WETH_USDC
1146 | | );
1147 | | _setUintDataStoreCall(
1148 | | DEPLOYER,
1149 | | "FUNDING_DECREASE_FACTOR_PER_SECOND",
1150 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1151 | | market_WETH_WETH_USDC
1152 | | );
1153 | | _setUintDataStoreCall(
1154 | | DEPLOYER,
1155 | | "MAX_FUNDING_FACTOR_PER_SECOND",
1156 | | MAX_FUNDING_FACTOR_PER_SECOND,
1157 | | market_WETH_WETH_USDC
1158 | | );
1159 | | _setUintDataStoreCall(
1160 | | DEPLOYER,
1161 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1162 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1163 | | market_WETH_WETH_USDC
1164 | | );
1165 | |
1166 | | /**
1167 | | * 0_0 *
1168 | | * --- Config for market_WETH_WETH_USDT ---
1169 | | */
1170 | | _setUintDataStoreCall(
1171 | | DEPLOYER,
1172 | | "MAX_POOL_AMOUNT",
1173 | | MAX_POOL_AMOUNT_WETH,
1174 | | market_WETH_WETH_USDT,
1175 | | address(WETH)
1176 | | );
1177 | | _setUintDataStoreCall(
1178 | | DEPLOYER,
1179 | | "MAX_POOL_AMOUNT",
1180 | | MAX_POOL_AMOUNT_USDT,
1181 | | market_WETH_WETH_USDT,
1182 | | address(USDT)
1183 | | );
1184 | | _setUintDataStoreCall(
1185 | | DEPLOYER,
1186 | | "MAX_POOL_USD_FOR_DEPOSIT",
1187 | | MAX_POOL_USD_FOR_DEPOSIT_WETH,
1188 | | market_WETH_WETH_USDT,
1189 | | address(WETH)
1190 | | );
1191 | | _setUintDataStoreCall(
1192 | | DEPLOYER,
1193 | | "MAX_POOL_USD_FOR_DEPOSIT",
1194 | | MAX_POOL_AMOUNT_USDT,
1195 | | market_WETH_WETH_USDT,
1196 | | address(USDT)
1197 | | );
1198 | | _setUintDataStoreCall(
1199 | | DEPLOYER,
1200 | | "MIN_COLLATERAL_FACTOR",
1201 | | MIN_COLLATERAL_FACTOR,
1202 | | market_WETH_WETH_USDT
1203 | | );
1204 | | _setUintDataStoreCall(
1205 | | DEPLOYER,
1206 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
1207 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG,
1208 | | market_WETH_WETH_USDT,
1209 | | true
1210 | | );
1211 | | _setUintDataStoreCall(
1212 | | DEPLOYER,
1213 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
1214 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT,
1215 | | market_WETH_WETH_USDT,
1216 | | false
1217 | | );
1218 | | _setUintDataStoreCall(
1219 | | DEPLOYER,
1220 | | "MAX_OPEN_INTEREST",
1221 | | MAX_OPEN_INTEREST_LONG,
1222 | | market_WETH_WETH_USDT,
1223 | | true
1224 | | );
1225 | | _setUintDataStoreCall(
1226 | | DEPLOYER,
1227 | | "MAX_OPEN_INTEREST",
1228 | | MAX_OPEN_INTEREST_SHORT,
1229 | | market_WETH_WETH_USDT,
1230 | | false
1231 | | );
1232 | | _setUintDataStoreCall(
1233 | | DEPLOYER,
1234 | | "RESERVE_FACTOR",
1235 | | RESERVE_FACTOR_LONG,
1236 | | market_WETH_WETH_USDT,
1237 | | true
1238 | | );
1239 | | _setUintDataStoreCall(
1240 | | DEPLOYER,
1241 | | "RESERVE_FACTOR",
1242 | | RESERVE_FACTOR_SHORT,
1243 | | market_WETH_WETH_USDT,
1244 | | false
1245 | | );
1246 | | _setUintDataStoreCall(
1247 | | DEPLOYER,
1248 | | "OPEN_INTEREST_RESERVE_FACTOR",
1249 | | OPEN_INTEREST_RESERVE_FACTOR_LONG,
1250 | | market_WETH_WETH_USDT,
1251 | | true
1252 | | );
1253 | | _setUintDataStoreCall(
1254 | | DEPLOYER,
1255 | | "OPEN_INTEREST_RESERVE_FACTOR",
1256 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT,
1257 | | market_WETH_WETH_USDT,
1258 | | false
1259 | | );
1260 | |
1261 | | _setUintDataStoreCall(
1262 | | DEPLOYER,
1263 | | "MAX_PNL_FACTOR",
1264 | | "MAX_PNL_FACTOR_FOR_TRADERS",
1265 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG,
1266 | | market_WETH_WETH_USDT,
1267 | | true
1268 | | );
1269 | | _setUintDataStoreCall(
1270 | | DEPLOYER,
1271 | | "MAX_PNL_FACTOR",
1272 | | "MAX_PNL_FACTOR_FOR_TRADERS",
1273 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT,
1274 | | market_WETH_WETH_USDT,
1275 | | false
1276 | | );
1277 | | _setUintDataStoreCall(
1278 | | DEPLOYER,
1279 | | "MAX_PNL_FACTOR",
1280 | | "MAX_PNL_FACTOR_FOR_ADL",
1281 | | MAX_PNL_FACTOR_FOR_ADL_LONG,
1282 | | market_WETH_WETH_USDT,
1283 | | true
1284 | | );
1285 | | _setUintDataStoreCall(
1286 | | DEPLOYER,
1287 | | "MAX_PNL_FACTOR",
1288 | | "MAX_PNL_FACTOR_FOR_ADL",
1289 | | MAX_PNL_FACTOR_FOR_ADL_SHORT,
1290 | | market_WETH_WETH_USDT,
1291 | | false
1292 | | );
1293 | | _setUintDataStoreCall(
1294 | | DEPLOYER,
1295 | | "MIN_PNL_FACTOR_AFTER_ADL",
1296 | | MIN_PNL_FACTOR_AFTER_ADL_LONG,
1297 | | market_WETH_WETH_USDT,
1298 | | true
1299 | | );
1300 | | _setUintDataStoreCall(
1301 | | DEPLOYER,
1302 | | "MIN_PNL_FACTOR_AFTER_ADL",
1303 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT,
1304 | | market_WETH_WETH_USDT,
1305 | | false
1306 | | );
1307 | | _setUintDataStoreCall(
1308 | | DEPLOYER,
1309 | | "MAX_PNL_FACTOR",
1310 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1311 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG,
1312 | | market_WETH_WETH_USDT,
1313 | | true
1314 | | );
1315 | | _setUintDataStoreCall(
1316 | | DEPLOYER,
1317 | | "MAX_PNL_FACTOR",
1318 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1319 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT,
1320 | | market_WETH_WETH_USDT,
1321 | | false
1322 | | );
1323 | | _setUintDataStoreCall(
1324 | | DEPLOYER,
1325 | | "MAX_PNL_FACTOR",
1326 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1327 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG,
1328 | | market_WETH_WETH_USDT,
1329 | | true
1330 | | );
1331 | | _setUintDataStoreCall(
1332 | | DEPLOYER,
1333 | | "MAX_PNL_FACTOR",
1334 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1335 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT,
1336 | | market_WETH_WETH_USDT,
1337 | | false
1338 | | );
1339 | | _setUintDataStoreCall(
1340 | | DEPLOYER,
1341 | | "TOKEN_TRANSFER_GAS_LIMIT",
1342 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT,
1343 | | market_WETH_WETH_USDT
1344 | | );
1345 | | _setUintDataStoreCall(
1346 | | DEPLOYER,
1347 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS",
1348 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,
1349 | | market_WETH_WETH_USDT
1350 | | );
1351 | | _setUintDataStoreCall(
1352 | | DEPLOYER,
1353 | | "POSITION_IMPACT_FACTOR",
1354 | | POSITION_IMPACT_FACTOR_POSITIVE,
1355 | | market_WETH_WETH_USDT,
1356 | | true
1357 | | );
1358 | | _setUintDataStoreCall(
1359 | | DEPLOYER,
1360 | | "POSITION_IMPACT_FACTOR",
1361 | | POSITION_IMPACT_FACTOR_NEGATIVE,
1362 | | market_WETH_WETH_USDT,
1363 | | false
1364 | | );
1365 | |
1366 | | _setUintDataStoreCall(
1367 | | DEPLOYER,
1368 | | "SWAP_FEE_FACTOR",
1369 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT,
1370 | | market_WETH_WETH_USDT,
1371 | | true
1372 | | );
1373 | |
1374 | | _setUintDataStoreCall(
1375 | | DEPLOYER,
1376 | | "SWAP_FEE_FACTOR",
1377 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT,
1378 | | market_WETH_WETH_USDT,
1379 | | false
1380 | | );
1381 | |
1382 | | _setUintDataStoreCall(
1383 | | DEPLOYER,
1384 | | "ATOMIC_SWAP_FEE_FACTOR",
1385 | | ATOMIC_SWAP_FEE_FACTOR,
1386 | | market_WETH_WETH_USDT
1387 | | );
1388 | | _setUintDataStoreCall(
1389 | | DEPLOYER,
1390 | | "FUNDING_FACTOR",
1391 | | FUNDING_FACTOR,
1392 | | market_WETH_WETH_USDT
1393 | | );
1394 | |
1395 | | _setUintDataStoreCall(
1396 | | DEPLOYER,
1397 | | "FUNDING_EXPONENT_FACTOR",
1398 | | FUNDING_EXPONENT_FACTOR,
1399 | | market_WETH_WETH_USDT
1400 | | );
1401 | | _setUintDataStoreCall(
1402 | | DEPLOYER,
1403 | | "THRESHOLD_FOR_STABLE_FUNDING",
1404 | | THRESHOLD_FOR_STABLE_FUNDING,
1405 | | market_WETH_WETH_USDT
1406 | | );
1407 | |
1408 | | _setUintDataStoreCall(
1409 | | DEPLOYER,
1410 | | "THRESHOLD_FOR_DECREASE_FUNDING",
1411 | | THRESHOLD_FOR_DECREASE_FUNDING,
1412 | | market_WETH_WETH_USDT
1413 | | );
1414 | | _setUintDataStoreCall(
1415 | | DEPLOYER,
1416 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1417 | | FUNDING_INCREASE_FACTOR_PER_SECOND,
1418 | | market_WETH_WETH_USDT
1419 | | );
1420 | | _setUintDataStoreCall(
1421 | | DEPLOYER,
1422 | | "FUNDING_DECREASE_FACTOR_PER_SECOND",
1423 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1424 | | market_WETH_WETH_USDT
1425 | | );
1426 | | _setUintDataStoreCall(
1427 | | DEPLOYER,
1428 | | "MAX_FUNDING_FACTOR_PER_SECOND",
1429 | | MAX_FUNDING_FACTOR_PER_SECOND,
1430 | | market_WETH_WETH_USDT
1431 | | );
1432 | | _setUintDataStoreCall(
1433 | | DEPLOYER,
1434 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1435 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1436 | | market_WETH_WETH_USDT
1437 | | );
1438 | | /**
1439 | | * 0_0 *
1440 | | * --- Config for market_0_WETH_USDC ---
1441 | | */
1442 | | _setUintDataStoreCall(
1443 | | DEPLOYER,
1444 | | "TOKEN_TRANSFER_GAS_LIMIT",
1445 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT,
1446 | | market_0_WETH_USDC
1447 | | );
1448 | | _setUintDataStoreCall(
1449 | | DEPLOYER,
1450 | | "MAX_POOL_AMOUNT",
1451 | | MAX_POOL_AMOUNT_WETH,
1452 | | market_0_WETH_USDC,
1453 | | address(WETH)
1454 | | );
1455 | | _setUintDataStoreCall(
1456 | | DEPLOYER,
1457 | | "MAX_POOL_AMOUNT",
1458 | | MAX_POOL_AMOUNT_USDC,
1459 | | market_0_WETH_USDC,
1460 | | address(USDC)
1461 | | );
1462 | | _setUintDataStoreCall(
1463 | | DEPLOYER,
1464 | | "MAX_POOL_USD_FOR_DEPOSIT",
1465 | | MAX_POOL_USD_FOR_DEPOSIT_WETH,
1466 | | market_0_WETH_USDC,
1467 | | address(WETH)
1468 | | );
1469 | | _setUintDataStoreCall(
1470 | | DEPLOYER,
1471 | | "MAX_POOL_USD_FOR_DEPOSIT",
1472 | | MAX_POOL_USD_FOR_DEPOSIT_USDC,
1473 | | market_0_WETH_USDC,
1474 | | address(USDC)
1475 | | );
1476 | |
1477 | | /**
1478 | | * 0_0 *
1479 | | * --- Config for market_WBTC_WBTC_USDC ---
1480 | | */
1481 | | _setUintDataStoreCall(
1482 | | DEPLOYER,
1483 | | "MAX_POOL_AMOUNT",
1484 | | MAX_POOL_AMOUNT_WBTC,
1485 | | market_WBTC_WBTC_USDC,
1486 | | address(WBTC)
1487 | | );
1488 | | _setUintDataStoreCall(
1489 | | DEPLOYER,
1490 | | "MAX_POOL_AMOUNT",
1491 | | MAX_POOL_AMOUNT_USDC,
1492 | | market_WBTC_WBTC_USDC,
1493 | | address(USDC)
1494 | | );
1495 | | _setUintDataStoreCall(
1496 | | DEPLOYER,
1497 | | "MAX_POOL_USD_FOR_DEPOSIT",
1498 | | MAX_POOL_USD_FOR_DEPOSIT_WBTC,
1499 | | market_WBTC_WBTC_USDC,
1500 | | address(WBTC)
1501 | | );
1502 | | _setUintDataStoreCall(
1503 | | DEPLOYER,
1504 | | "MAX_POOL_USD_FOR_DEPOSIT",
1505 | | MAX_POOL_USD_FOR_DEPOSIT_USDC,
1506 | | market_WBTC_WBTC_USDC,
1507 | | address(USDC)
1508 | | );
1509 | | _setUintDataStoreCall(
1510 | | DEPLOYER,
1511 | | "MIN_COLLATERAL_FACTOR",
1512 | | MIN_COLLATERAL_FACTOR,
1513 | | market_WBTC_WBTC_USDC
1514 | | );
1515 | | _setUintDataStoreCall(
1516 | | DEPLOYER,
1517 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
1518 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG,
1519 | | market_WBTC_WBTC_USDC,
1520 | | true
1521 | | );
1522 | | _setUintDataStoreCall(
1523 | | DEPLOYER,
1524 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER",
1525 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT,
1526 | | market_WBTC_WBTC_USDC,
1527 | | false
1528 | | );
1529 | | _setUintDataStoreCall(
1530 | | DEPLOYER,
1531 | | "MAX_OPEN_INTEREST",
1532 | | MAX_OPEN_INTEREST_LONG,
1533 | | market_WBTC_WBTC_USDC,
1534 | | true
1535 | | );
1536 | | _setUintDataStoreCall(
1537 | | DEPLOYER,
1538 | | "MAX_OPEN_INTEREST",
1539 | | MAX_OPEN_INTEREST_SHORT,
1540 | | market_WBTC_WBTC_USDC,
1541 | | false
1542 | | );
1543 | | _setUintDataStoreCall(
1544 | | DEPLOYER,
1545 | | "RESERVE_FACTOR",
1546 | | RESERVE_FACTOR_LONG,
1547 | | market_WBTC_WBTC_USDC,
1548 | | true
1549 | | );
1550 | | _setUintDataStoreCall(
1551 | | DEPLOYER,
1552 | | "RESERVE_FACTOR",
1553 | | RESERVE_FACTOR_SHORT,
1554 | | market_WBTC_WBTC_USDC,
1555 | | false
1556 | | );
1557 | | _setUintDataStoreCall(
1558 | | DEPLOYER,
1559 | | "OPEN_INTEREST_RESERVE_FACTOR",
1560 | | OPEN_INTEREST_RESERVE_FACTOR_LONG,
1561 | | market_WBTC_WBTC_USDC,
1562 | | true
1563 | | );
1564 | | _setUintDataStoreCall(
1565 | | DEPLOYER,
1566 | | "OPEN_INTEREST_RESERVE_FACTOR",
1567 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT,
1568 | | market_WBTC_WBTC_USDC,
1569 | | false
1570 | | );
1571 | |
1572 | | _setUintDataStoreCall(
1573 | | DEPLOYER,
1574 | | "MAX_PNL_FACTOR",
1575 | | "MAX_PNL_FACTOR_FOR_TRADERS",
1576 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG,
1577 | | market_WBTC_WBTC_USDC,
1578 | | true
1579 | | );
1580 | | _setUintDataStoreCall(
1581 | | DEPLOYER,
1582 | | "MAX_PNL_FACTOR",
1583 | | "MAX_PNL_FACTOR_FOR_TRADERS",
1584 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT,
1585 | | market_WBTC_WBTC_USDC,
1586 | | false
1587 | | );
1588 | | _setUintDataStoreCall(
1589 | | DEPLOYER,
1590 | | "MAX_PNL_FACTOR",
1591 | | "MAX_PNL_FACTOR_FOR_ADL",
1592 | | MAX_PNL_FACTOR_FOR_ADL_LONG,
1593 | | market_WBTC_WBTC_USDC,
1594 | | true
1595 | | );
1596 | | _setUintDataStoreCall(
1597 | | DEPLOYER,
1598 | | "MAX_PNL_FACTOR",
1599 | | "MAX_PNL_FACTOR_FOR_ADL",
1600 | | MAX_PNL_FACTOR_FOR_ADL_SHORT,
1601 | | market_WBTC_WBTC_USDC,
1602 | | false
1603 | | );
1604 | | _setUintDataStoreCall(
1605 | | DEPLOYER,
1606 | | "MIN_PNL_FACTOR_AFTER_ADL",
1607 | | MIN_PNL_FACTOR_AFTER_ADL_LONG,
1608 | | market_WBTC_WBTC_USDC,
1609 | | true
1610 | | );
1611 | | _setUintDataStoreCall(
1612 | | DEPLOYER,
1613 | | "MIN_PNL_FACTOR_AFTER_ADL",
1614 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT,
1615 | | market_WBTC_WBTC_USDC,
1616 | | false
1617 | | );
1618 | | _setUintDataStoreCall(
1619 | | DEPLOYER,
1620 | | "MAX_PNL_FACTOR",
1621 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1622 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG,
1623 | | market_WBTC_WBTC_USDC,
1624 | | true
1625 | | );
1626 | | _setUintDataStoreCall(
1627 | | DEPLOYER,
1628 | | "MAX_PNL_FACTOR",
1629 | | "MAX_PNL_FACTOR_FOR_DEPOSITS",
1630 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT,
1631 | | market_WBTC_WBTC_USDC,
1632 | | false
1633 | | );
1634 | | _setUintDataStoreCall(
1635 | | DEPLOYER,
1636 | | "MAX_PNL_FACTOR",
1637 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1638 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG,
1639 | | market_WBTC_WBTC_USDC,
1640 | | true
1641 | | );
1642 | | _setUintDataStoreCall(
1643 | | DEPLOYER,
1644 | | "MAX_PNL_FACTOR",
1645 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS",
1646 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT,
1647 | | market_WBTC_WBTC_USDC,
1648 | | false
1649 | | );
1650 | | _setUintDataStoreCall(
1651 | | DEPLOYER,
1652 | | "TOKEN_TRANSFER_GAS_LIMIT",
1653 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT,
1654 | | market_WBTC_WBTC_USDC
1655 | | );
1656 | | _setUintDataStoreCall(
1657 | | DEPLOYER,
1658 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS",
1659 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,
1660 | | market_WBTC_WBTC_USDC
1661 | | );
1662 | | _setUintDataStoreCall(
1663 | | DEPLOYER,
1664 | | "POSITION_IMPACT_FACTOR",
1665 | | POSITION_IMPACT_FACTOR_POSITIVE,
1666 | | market_WBTC_WBTC_USDC,
1667 | | true
1668 | | );
1669 | | _setUintDataStoreCall(
1670 | | DEPLOYER,
1671 | | "POSITION_IMPACT_FACTOR",
1672 | | POSITION_IMPACT_FACTOR_NEGATIVE,
1673 | | market_WBTC_WBTC_USDC,
1674 | | false
1675 | | );
1676 | |
1677 | | _setUintDataStoreCall(
1678 | | DEPLOYER,
1679 | | "SWAP_FEE_FACTOR",
1680 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT,
1681 | | market_WBTC_WBTC_USDC,
1682 | | true
1683 | | );
1684 | |
1685 | | _setUintDataStoreCall(
1686 | | DEPLOYER,
1687 | | "SWAP_FEE_FACTOR",
1688 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT,
1689 | | market_WBTC_WBTC_USDC,
1690 | | false
1691 | | );
1692 | |
1693 | | _setUintDataStoreCall(
1694 | | DEPLOYER,
1695 | | "ATOMIC_SWAP_FEE_FACTOR",
1696 | | ATOMIC_SWAP_FEE_FACTOR,
1697 | | market_WBTC_WBTC_USDC
1698 | | );
1699 | |
1700 | | _setUintDataStoreCall(
1701 | | DEPLOYER,
1702 | | "FUNDING_FACTOR",
1703 | | FUNDING_FACTOR,
1704 | | market_WBTC_WBTC_USDC
1705 | | );
1706 | |
1707 | | _setUintDataStoreCall(
1708 | | DEPLOYER,
1709 | | "FUNDING_EXPONENT_FACTOR",
1710 | | FUNDING_EXPONENT_FACTOR,
1711 | | market_WBTC_WBTC_USDC
1712 | | );
1713 | | _setUintDataStoreCall(
1714 | | DEPLOYER,
1715 | | "THRESHOLD_FOR_STABLE_FUNDING",
1716 | | THRESHOLD_FOR_STABLE_FUNDING,
1717 | | market_WBTC_WBTC_USDC
1718 | | );
1719 | |
1720 | | _setUintDataStoreCall(
1721 | | DEPLOYER,
1722 | | "THRESHOLD_FOR_DECREASE_FUNDING",
1723 | | THRESHOLD_FOR_DECREASE_FUNDING,
1724 | | market_WBTC_WBTC_USDC
1725 | | );
1726 | | _setUintDataStoreCall(
1727 | | DEPLOYER,
1728 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1729 | | FUNDING_INCREASE_FACTOR_PER_SECOND,
1730 | | market_WBTC_WBTC_USDC
1731 | | );
1732 | | _setUintDataStoreCall(
1733 | | DEPLOYER,
1734 | | "FUNDING_DECREASE_FACTOR_PER_SECOND",
1735 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1736 | | market_WBTC_WBTC_USDC
1737 | | );
1738 | | _setUintDataStoreCall(
1739 | | DEPLOYER,
1740 | | "MAX_FUNDING_FACTOR_PER_SECOND",
1741 | | MAX_FUNDING_FACTOR_PER_SECOND,
1742 | | market_WBTC_WBTC_USDC
1743 | | );
1744 | | _setUintDataStoreCall(
1745 | | DEPLOYER,
1746 | | "FUNDING_INCREASE_FACTOR_PER_SECOND",
1747 | | FUNDING_DECREASE_FACTOR_PER_SECOND,
1748 | | market_WBTC_WBTC_USDC
1749 | | );
1750 | |
1751 | | //v2.1 remediations
1752 | | _setUintDataStoreCall(
1753 | | DEPLOYER,
1754 | | "MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS",
1755 | | MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS,
1756 | | address(0)
1757 | | );
1758 | | _setUintDataStoreCall(
1759 | | DEPLOYER,
1760 | | "EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1",
1761 | | EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1,
1762 | | address(0)
1763 | | );
1764 | | }
1765 | |
1766 | | function userSetup() internal {
1767 | | vm.deal(DEPLOYER, 10000e18);
1768 | | vm.deal(USER0, 10000e18);
1769 | | vm.deal(USER1, 10000e18);
1770 | | vm.deal(USER2, 10000e18);
1771 | | vm.deal(USER3, 10000e18);
1772 | | vm.deal(USER4, 10000e18);
1773 | | vm.deal(USER5, 10000e18);
1774 | | vm.deal(USER6, 10000e18);
1775 | | vm.deal(USER7, 10000e18);
1776 | | vm.deal(USER8, 10000e18);
1777 | | vm.deal(USER9, 10000e18);
1778 | | vm.deal(USER10, 10000e18);
1779 | | vm.deal(USER11, 10000e18);
1780 | | vm.deal(USER12, 10000e18);
1781 | | vm.deal(USER13, 10000e18);
1782 | | vm.deal(paraswapDeployer, 10000e18);
1783 | | }
1784 | |
1785 | | function deployCallbackCotracts() internal {
1786 | | callback = new GasFeeCallbackReceiver();
1787 | | }
1788 | |
1789 | | function deployGammaVault1x_WETHUSDC() internal {
1790 | | mockData = new MockData();
1791 | |
1792 | | proxyAdmin = new ProxyAdmin();
1793 | |
1794 | | gmxUtilsLogic_GammaVault1x_WETHUSDC = new GmxUtils();
1795 | | bytes memory data = abi.encodeWithSelector(
1796 | | GmxUtils.initialize.selector,
1797 | | address(orderHandler),
1798 | | address(exchangeRouter),
1799 | | address(dataStore),
1800 | | address(orderVault),
1801 | | address(reader),
1802 | | address(referralStorage),
1803 | | address(router)
1804 | | );
1805 | |
1806 | | gmxUtils_GammaVault1x_WETHUSDC = address(
1807 | | new TransparentUpgradeableProxy(
1808 | | address(gmxUtilsLogic_GammaVault1x_WETHUSDC),
1809 | | address(proxyAdmin),
1810 | | data
1811 | | )
1812 | | );
1813 | | payable(gmxUtils_GammaVault1x_WETHUSDC).transfer(10 ether);
1814 | |
1815 | | perpetualVault_GammaVault1x_WETHUSDC = new PerpetualVaultLens();
1816 | | data = abi.encodeWithSelector(
1817 | | perpetualVault_GammaVault1x_WETHUSDC.initialize.selector,
1818 | | "vault_1x_WETH/USDC", //_name
1819 | | market_WETH_WETH_USDC, //_market
1820 | | gammaKeeper, //_keeper
1821 | | treasury_GammaVault1x_WETHUSDC, //_treasury
1822 | | gmxUtils_GammaVault1x_WETHUSDC, //_gmxUtils
1823 | | 1e8,
1824 | | 1e28
1825 | | );
1826 | | vault_GammaVault1x_WETHUSDC = payable(
1827 | | new TransparentUpgradeableProxy(
1828 | | address(perpetualVault_GammaVault1x_WETHUSDC),
1829 | | address(proxyAdmin),
1830 | | data
1831 | | )
1832 | | );
1833 | | }
1834 | |
1835 | | function deployGammaVault2x_WETHUSDC() internal {
1836 | | proxyAdmin = new ProxyAdmin();
1837 | |
1838 | | gmxUtilsLogic_GammaVault2x_WETHUSDC = new GmxUtils();
1839 | | bytes memory data = abi.encodeWithSelector(
1840 | | GmxUtils.initialize.selector,
1841 | | address(orderHandler),
1842 | | address(exchangeRouter),
1843 | | address(dataStore),
1844 | | address(orderVault),
1845 | | address(reader),
1846 | | address(referralStorage),
1847 | | address(router)
1848 | | );
1849 | |
1850 | | gmxUtils_GammaVault2x_WETHUSDC = address(
1851 | | new TransparentUpgradeableProxy(
1852 | | address(gmxUtilsLogic_GammaVault2x_WETHUSDC),
1853 | | address(proxyAdmin),
1854 | | data
1855 | | )
1856 | | );
1857 | | payable(gmxUtils_GammaVault2x_WETHUSDC).transfer(10 ether);
1858 | |
1859 | | perpetualVault_GammaVault2x_WETHUSDC = new PerpetualVaultLens();
1860 | | data = abi.encodeWithSelector(
1861 | | perpetualVault_GammaVault2x_WETHUSDC.initialize.selector,
1862 | | "vault_2x_WETH/USDC", //_name
1863 | | market_WETH_WETH_USDC, //_market
1864 | | gammaKeeper, //_keeper
1865 | | treasury_GammaVault2x_WETHUSDC, //_treasury
1866 | | gmxUtils_GammaVault2x_WETHUSDC, //_gmxUtils
1867 | | 1e8,
1868 | | 1e28
1869 | | );
1870 | | vault_GammaVault2x_WETHUSDC = payable(
1871 | | new TransparentUpgradeableProxy(
1872 | | address(perpetualVault_GammaVault2x_WETHUSDC),
1873 | | address(proxyAdmin),
1874 | | data
1875 | | )
1876 | | );
1877 | | }
1878 | |
1879 | | function deployGammaVault3x_WETHUSDC() internal {
1880 | | gmxUtilsLogic_GammaVault3x_WETHUSDC = new GmxUtils();
1881 | | bytes memory data = abi.encodeWithSelector(
1882 | | GmxUtils.initialize.selector,
1883 | | address(orderHandler),
1884 | | address(exchangeRouter),
1885 | | address(dataStore),
1886 | | address(orderVault),
1887 | | address(reader),
1888 | | address(referralStorage),
1889 | | address(router)
1890 | | );
1891 | |
1892 | | gmxUtils_GammaVault3x_WETHUSDC = address(
1893 | | new TransparentUpgradeableProxy(
1894 | | address(gmxUtilsLogic_GammaVault3x_WETHUSDC),
1895 | | address(proxyAdmin),
1896 | | data
1897 | | )
1898 | | );
1899 | | payable(gmxUtils_GammaVault3x_WETHUSDC).transfer(10 ether);
1900 | |
1901 | | perpetualVault_GammaVault3x_WETHUSDC = new PerpetualVaultLens();
1902 | | data = abi.encodeWithSelector(
1903 | | perpetualVault_GammaVault3x_WETHUSDC.initialize.selector,
1904 | | "vault_3x_WETH/USDC", //_name
1905 | | market_WETH_WETH_USDC, //_market
1906 | | gammaKeeper, //_keeper
1907 | | treasury_GammaVault3x_WETHUSDC, //_treasury
1908 | | gmxUtils_GammaVault3x_WETHUSDC, //_gmxUtils
1909 | | 1e8,
1910 | | 1e28
1911 | | );
1912 | | vault_GammaVault3x_WETHUSDC = payable(
1913 | | new TransparentUpgradeableProxy(
1914 | | address(perpetualVault_GammaVault3x_WETHUSDC),
1915 | | address(proxyAdmin),
1916 | | data
1917 | | )
1918 | | );
1919 | | }
1920 | |
1921 | | function deployGammaVault1x_WBTCUSDC() internal {
1922 | | gmxUtilsLogic_GammaVault1x_WBTCUSDC = new GmxUtils();
1923 | | bytes memory data = abi.encodeWithSelector(
1924 | | GmxUtils.initialize.selector,
1925 | | address(orderHandler),
1926 | | address(exchangeRouter),
1927 | | address(dataStore),
1928 | | address(orderVault),
1929 | | address(reader),
1930 | | address(referralStorage),
1931 | | address(router)
1932 | | );
1933 | |
1934 | | gmxUtils_GammaVault1x_WBTCUSDC = address(
1935 | | new TransparentUpgradeableProxy(
1936 | | address(gmxUtilsLogic_GammaVault1x_WBTCUSDC),
1937 | | address(proxyAdmin),
1938 | | data
1939 | | )
1940 | | );
1941 | | payable(gmxUtils_GammaVault1x_WBTCUSDC).transfer(10 ether);
1942 | |
1943 | | perpetualVault_GammaVaul1x_WBTCUSDC = new PerpetualVaultLens();
1944 | | data = abi.encodeWithSelector(
1945 | | perpetualVault_GammaVaul1x_WBTCUSDC.initialize.selector,
1946 | | "vault_1x_WBTC/USDC", //_name
1947 | | market_WBTC_WBTC_USDC, //_market
1948 | | gammaKeeper, //_keeper
1949 | | treasury_GammaVault1x_WBTCUSDC, //_treasury
1950 | | gmxUtils_GammaVault1x_WBTCUSDC, //_gmxUtils
1951 | | 1e8,
1952 | | 1e28
1953 | | );
1954 | | vault_GammaVault1x_WBTCUSDC = payable(
1955 | | new TransparentUpgradeableProxy(
1956 | | address(perpetualVault_GammaVaul1x_WBTCUSDC),
1957 | | address(proxyAdmin),
1958 | | data
1959 | | )
1960 | | );
1961 | | }
1962 | |
1963 | | function deployGammaVault2x_WBTCUSDC() internal {
1964 | | gmxUtilsLogic_GammaVault2x_WBTCUSDC = new GmxUtils();
1965 | | bytes memory data = abi.encodeWithSelector(
1966 | | GmxUtils.initialize.selector,
1967 | | address(orderHandler),
1968 | | address(exchangeRouter),
1969 | | address(dataStore),
1970 | | address(orderVault),
1971 | | address(reader),
1972 | | address(referralStorage),
1973 | | address(router)
1974 | | );
1975 | |
1976 | | gmxUtils_GammaVault2x_WBTCUSDC = address(
1977 | | new TransparentUpgradeableProxy(
1978 | | address(gmxUtilsLogic_GammaVault2x_WBTCUSDC),
1979 | | address(proxyAdmin),
1980 | | data
1981 | | )
1982 | | );
1983 | | payable(gmxUtils_GammaVault2x_WBTCUSDC).transfer(10 ether);
1984 | |
1985 | | perpetualVault_GammaVault2x_WBTCUSDC = new PerpetualVaultLens();
1986 | | data = abi.encodeWithSelector(
1987 | | perpetualVault_GammaVault2x_WBTCUSDC.initialize.selector,
1988 | | "vault_2x_WBTC/USDC", //_name
1989 | | market_WBTC_WBTC_USDC, //_market
1990 | | gammaKeeper, //_keeper
1991 | | treasury_GammaVault2x_WBTCUSDC, //_treasury
1992 | | gmxUtils_GammaVault2x_WBTCUSDC, //_gmxUtils
1993 | | 1e8,
1994 | | 1e28
1995 | | );
1996 | | vault_GammaVault2x_WBTCUSDC = payable(
1997 | | new TransparentUpgradeableProxy(
1998 | | address(perpetualVault_GammaVault2x_WBTCUSDC),
1999 | | address(proxyAdmin),
2000 | | data
2001 | | )
2002 | | );
2003 | | }
2004 | |
2005 | | function deployGammaVault3x_WBTCUSDC() internal {
2006 | | gmxUtilsLogic_GammaVault3x_WBTCUSDC = new GmxUtils();
2007 | | bytes memory data = abi.encodeWithSelector(
2008 | | GmxUtils.initialize.selector,
2009 | | address(orderHandler),
2010 | | address(exchangeRouter),
2011 | | address(dataStore),
2012 | | address(orderVault),
2013 | | address(reader),
2014 | | address(referralStorage),
2015 | | address(router)
2016 | | );
2017 | |
2018 | | gmxUtils_GammaVault3x_WBTCUSDC = address(
2019 | | new TransparentUpgradeableProxy(
2020 | | address(gmxUtilsLogic_GammaVault3x_WBTCUSDC),
2021 | | address(proxyAdmin),
2022 | | data
2023 | | )
2024 | | );
2025 | | payable(gmxUtils_GammaVault3x_WBTCUSDC).transfer(10 ether);
2026 | |
2027 | | perpetualVault_GammaVault3x_WBTCUSDC = new PerpetualVaultLens();
2028 | | data = abi.encodeWithSelector(
2029 | | perpetualVault_GammaVault3x_WBTCUSDC.initialize.selector,
2030 | | "vault_3x_WBTC/USDC", //_name
2031 | | market_WBTC_WBTC_USDC, //_market
2032 | | gammaKeeper, //_keeper
2033 | | treasury_GammaVault3x_WBTCUSDC, //_treasury
2034 | | gmxUtils_GammaVault3x_WBTCUSDC, //_gmxUtils
2035 | | 1e8,
2036 | | 1e28
2037 | | );
2038 | | vault_GammaVault3x_WBTCUSDC = payable(
2039 | | new TransparentUpgradeableProxy(
2040 | | address(perpetualVault_GammaVault3x_WBTCUSDC),
2041 | | address(proxyAdmin),
2042 | | data
2043 | | )
2044 | | );
2045 | | }
2046 | |
2047 | | function deployDex() internal {
2048 | | // vm.prank(paraswapDeployer); //NOTE: this prank doesnt work in setup, deploying with hevm address
2049 | | vm.prank(HEVM_INITIAL_ADDRESS); //for a foundry compatibility
2050 | | mockDex = new MockDex();
2051 | | if (msg.sender == HEVM_INITIAL_ADDRESS) {
2052 | | //echidna
2053 | | fl.t(
2054 | | address(mockDex) ==
2055 | | address(0x78c362A5690447EA2BBC3E8008502efD13936F79),
2056 | | "Address of DEX should be Paraswap V5 Augustus Swapper"
2057 | | );
2058 | | } else if (msg.sender == FOUNDRY_DEFAULT_ADDRESS) {
2059 | | fl.t(
2060 | | address(mockDex) ==
2061 | | address(0x731a10897d267e19B34503aD902d0A29173Ba4B1),
2062 | | "Address of DEX should be Paraswap V5 Augustus Swapper"
2063 | | );
2064 | | }
2065 | |
2066 | | // fl.t(
2067 | | // address(mockDex) ==
2068 | | // address(0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57),
2069 | | // "Address of DEX should be Paraswap V5 Augustus Swapper"
2070 | | // ); //nonce = 1, nonce = 0 was minting WETH in GMXSetup
2071 | | }
2072 | |
2073 | * | function addLiquidityDex() public {
2074 | * | uint amountWETH = WETH.balanceOf(paraswapDeployer) / 2;
2075 | * | uint amountUSDC = USDC.balanceOf(paraswapDeployer) / 5;
2076 | * | uint amountWBTC = WBTC.balanceOf(paraswapDeployer) / 2;
2077 | |
2078 | *r | mockDex.createPair(
2079 | * | address(WETH),
2080 | * | address(USDC),
2081 | * | 3, //feePercentage
2082 | * | 100, //maxSwapPercentage
2083 | | "WETH/USDC Pair",
2084 | | "WETHUSDC"
2085 | | );
2086 | | vm.prank(paraswapDeployer);
2087 | | WETH.approve(address(mockDex), type(uint256).max);
2088 | | vm.prank(paraswapDeployer);
2089 | | USDC.approve(address(mockDex), type(uint256).max);
2090 | | vm.prank(paraswapDeployer);
2091 | | mockDex.addLiquidity(
2092 | | address(WETH),
2093 | | address(USDC),
2094 | | amountWETH,
2095 | | amountUSDC,
2096 | | 0,
2097 | | 0
2098 | | );
2099 | |
2100 | | mockDex.createPair(
2101 | | address(WBTC),
2102 | | address(USDC),
2103 | | 3, //feePercentage
2104 | | 100, //maxSwapPercentage
2105 | | "WBTC/USDC Pair",
2106 | | "WBTCUSDC"
2107 | | );
2108 | | vm.prank(paraswapDeployer);
2109 | | WBTC.approve(address(mockDex), type(uint256).max);
2110 | | vm.prank(paraswapDeployer);
2111 | | USDC.approve(address(mockDex), type(uint256).max);
2112 | | vm.prank(paraswapDeployer);
2113 | | mockDex.addLiquidity(
2114 | | address(WBTC),
2115 | | address(USDC),
2116 | | amountWBTC,
2117 | | amountUSDC,
2118 | | 0,
2119 | | 0
2120 | | );
2121 | | }
2122 | |
2123 | | function setVaultsArray() internal {
2124 | | VAULTS = [
2125 | | vault_GammaVault1x_WETHUSDC,
2126 | | vault_GammaVault2x_WETHUSDC,
2127 | | vault_GammaVault3x_WETHUSDC,
2128 | | vault_GammaVault1x_WBTCUSDC,
2129 | | vault_GammaVault2x_WBTCUSDC,
2130 | | vault_GammaVault3x_WBTCUSDC
2131 | | ];
2132 | | // vm.label(vault_GammaVault1x_WBTCUSDC, "vault_GammaVault1x_WBTCUSDC");
2133 | | // vm.label(vault_GammaVault2x_WBTCUSDC, "vault_GammaVault2x_WBTCUSDC");
2134 | | // vm.label(
2135 | | // gmxUtils_GammaVault3x_WBTCUSDC,
2136 | | // "gmxUtils_GammaVault3x_WBTCUSDC"
2137 | | // );
2138 | | // vm.label(vault_GammaVault1x_WETHUSDC, "vault_GammaVault1x_WETHUSDC");
2139 | | // vm.label(vault_GammaVault2x_WETHUSDC, "vault_GammaVault2x_WETHUSDC");
2140 | | // vm.label(vault_GammaVault3x_WETHUSDC, "vault_GammaVault3x_WETHUSDC");
2141 | | }
2142 | |
2143 | | function fillVaultMarketMap() internal {
2144 | | // Map WBTC-USDC vaults to their market
2145 | | vaultToMarket[vault_GammaVault1x_WBTCUSDC] = market_WBTC_WBTC_USDC;
2146 | | vaultToMarket[vault_GammaVault2x_WBTCUSDC] = market_WBTC_WBTC_USDC;
2147 | | vaultToMarket[vault_GammaVault3x_WBTCUSDC] = market_WBTC_WBTC_USDC;
2148 | |
2149 | | // Map WETH-USDC vaults to their market
2150 | | vaultToMarket[vault_GammaVault1x_WETHUSDC] = market_WETH_WETH_USDC;
2151 | | vaultToMarket[vault_GammaVault2x_WETHUSDC] = market_WETH_WETH_USDC;
2152 | | vaultToMarket[vault_GammaVault3x_WETHUSDC] = market_WETH_WETH_USDC;
2153 | | }
2154 | |
2155 | | function setRouterInVault() internal {
2156 | | PARASWAP_ROUTER = address(mockDex);
2157 | |
2158 | | PerpetualVaultLens(vault_GammaVault1x_WETHUSDC).setRouter(
2159 | | PARASWAP_ROUTER
2160 | | );
2161 | | PerpetualVaultLens(vault_GammaVault2x_WETHUSDC).setRouter(
2162 | | PARASWAP_ROUTER
2163 | | );
2164 | | PerpetualVaultLens(vault_GammaVault3x_WETHUSDC).setRouter(
2165 | | PARASWAP_ROUTER
2166 | | );
2167 | | PerpetualVaultLens(vault_GammaVault1x_WBTCUSDC).setRouter(
2168 | | PARASWAP_ROUTER
2169 | | );
2170 | | PerpetualVaultLens(vault_GammaVault2x_WBTCUSDC).setRouter(
2171 | | PARASWAP_ROUTER
2172 | | );
2173 | | PerpetualVaultLens(vault_GammaVault3x_WBTCUSDC).setRouter(
2174 | | PARASWAP_ROUTER
2175 | | );
2176 | | }
2177 | | }
2178 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzStorageVars.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "../utils/FuzzUtils.sol";
6 | | import "./FuzzGMXConfig.sol";
7 | |
8 | | /**
9 | | * 0_0 *
10 | | * --- Libraries imports ---
11 | | */
12 | |
13 | | //ADL
14 | | import "../../contracts/adl/AdlUtils.sol";
15 | |
16 | | //Gas
17 | | // import "../../contracts/gas/GasUtils.sol";
18 | |
19 | | //Fee
20 | | import "../../contracts/fee/FeeUtils.sol";
21 | | import "../../contracts/fee/FeeBatch.sol";
22 | |
23 | | //Order
24 | | import "../../contracts/order/BaseOrderUtils.sol";
25 | | import "../../contracts/order/OrderStoreUtils.sol";
26 | | import "../../contracts/order/OrderEventUtils.sol";
27 | | import "../../contracts/order/IncreaseOrderUtils.sol";
28 | | import "../../contracts/order/DecreaseOrderUtils.sol";
29 | | import "../../contracts/order/SwapOrderUtils.sol";
30 | | import "../../contracts/order/OrderUtils.sol";
31 | |
32 | | // Market
33 | | import "../../contracts/market/MarketStoreUtils.sol";
34 | | import "../../contracts/market/MarketEventUtils.sol";
35 | | import "../../contracts/market/MarketUtils.sol";
36 | |
37 | | //Pricing
38 | | import "../../contracts/pricing/SwapPricingUtils.sol";
39 | |
40 | | //Swap
41 | | import "../../contracts/swap/SwapUtils.sol";
42 | |
43 | | //Position
44 | | import "../../contracts/position/PositionStoreUtils.sol";
45 | | import "../../contracts/pricing/PositionPricingUtils.sol";
46 | | import "../../contracts/position/PositionUtils.sol";
47 | | import "../../contracts/position/PositionEventUtils.sol";
48 | | import "../../contracts/position/IncreasePositionUtils.sol";
49 | | import "../../contracts/position/DecreasePositionSwapUtils.sol";
50 | | import "../../contracts/position/DecreasePositionCollateralUtils.sol";
51 | | import "../../contracts/position/DecreasePositionUtils.sol";
52 | |
53 | | //Referral
54 | | import "../../contracts/referral/ReferralEventUtils.sol";
55 | |
56 | | //Other libs
57 | | import "../../contracts/token/TokenUtils.sol";
58 | | import "../../contracts/fee/FeeSwapUtils.sol";
59 | | import "../../contracts/order/Order.sol";
60 | | import "../../contracts/order/AutoCancelUtils.sol";
61 | | import "../../contracts/referral/ReferralTier.sol";
62 | | import "../../contracts/role/Role.sol";
63 | | import "../../contracts/deposit/Deposit.sol";
64 | | import "../../contracts/nonce/NonceUtils.sol";
65 | | import "../../contracts/fee/FeeBatchStoreUtils.sol";
66 | | import "../../contracts/test/ArrayTest.sol";
67 | | import "../../contracts/liquidation/LiquidationUtils.sol";
68 | | import "../../contracts/position/Position.sol";
69 | | import "../../contracts/position/DecreasePositionSwapUtils.sol";
70 | | import "../../contracts/position/PositionUtils.sol";
71 | | import "../../contracts/position/DecreasePositionUtils.sol";
72 | | import "../../contracts/position/PositionStoreUtils.sol";
73 | | import "../../contracts/position/PositionStoreUtils.sol";
74 | | import "../../contracts/position/DecreasePositionCollateralUtils.sol";
75 | | import "../../contracts/position/PositionEventUtils.sol";
76 | | import "../../contracts/position/IncreasePositionUtils.sol";
77 | | import "../../contracts/withdrawal/WithdrawalStoreUtils.sol";
78 | | import "../../contracts/withdrawal/ExecuteWithdrawalUtils.sol";
79 | | import "../../contracts/withdrawal/WithdrawalEventUtils.sol";
80 | | import "../../contracts/withdrawal/Withdrawal.sol";
81 | | import "../../contracts/withdrawal/WithdrawalUtils.sol";
82 | | import "../../contracts/oracle/ChainlinkPriceFeedUtils.sol";
83 | | import "../../contracts/oracle/OracleUtils.sol";
84 | | import "../../contracts/oracle/GmOracleUtils.sol";
85 | | import "../../contracts/utils/Uint256Mask.sol";
86 | | import "../../contracts/utils/Bits.sol";
87 | | import "../../contracts/utils/Cast.sol";
88 | | import "../../contracts/utils/AccountUtils.sol";
89 | | import "../../contracts/utils/Array.sol";
90 | | import "../../contracts/utils/Calc.sol";
91 | | import "../../contracts/utils/Precision.sol";
92 | | import "../../contracts/utils/Printer.sol";
93 | | import "../../contracts/utils/EnumerableValues.sol";
94 | | import "../../contracts/chain/Chain.sol";
95 | | import "../../contracts/adl/AdlUtils.sol";
96 | | import "../../contracts/price/Price.sol";
97 | | import "../../contracts/subaccount/SubaccountUtils.sol";
98 | | import "../../contracts/market/MarketPoolValueInfo.sol";
99 | | import "../../contracts/market/MarketUtils.sol";
100 | | import "../../contracts/market/MarketEventUtils.sol";
101 | | import "../../contracts/market/MarketStoreUtils.sol";
102 | | import "../../contracts/market/Market.sol";
103 | | import "../../contracts/feature/FeatureUtils.sol";
104 | | import "../../contracts/callback/CallbackUtils.sol";
105 | | import "../../contracts/data/Keys.sol";
106 | | import "../../contracts/error/ErrorUtils.sol";
107 | | import "../../contracts/error/Errors.sol";
108 | | import "../../contracts/pricing/PositionPricingUtils.sol";
109 | | import "../../contracts/pricing/PricingUtils.sol";
110 | | import "../../contracts/pricing/SwapPricingUtils.sol";
111 | | import "../../contracts/event/EventUtils.sol";
112 | |
113 | | //Test libs
114 | | import "../../contracts/test/MarketStoreUtilsTest.sol";
115 | | import "../../contracts/test/GasUsageTest.sol";
116 | | import "../../contracts/test/WithdrawalStoreUtilsTest.sol";
117 | | import "../../contracts/test/PricingUtilsTest.sol";
118 | | import "../../contracts/test/DepositStoreUtilsTest.sol";
119 | | import "../../contracts/test/OrderStoreUtilsTest.sol";
120 | | import "../../contracts/test/PositionStoreUtilsTest.sol";
121 | |
122 | | /**
123 | | * 0_0 *
124 | | * --- Contracts ---
125 | | */
126 | |
127 | | //Role
128 | | import "../../contracts/role/RoleStore.sol";
129 | |
130 | | //Data
131 | | import "../../contracts/data/DataStore.sol";
132 | |
133 | | //Mocks
134 | | import "../../contracts/mock/MintableToken.sol";
135 | | import "../../contracts/mock/WNT.sol";
136 | | import "../../contracts/mock/MockPriceFeed.sol";
137 | | import "../../contracts/mock/MockDataStreamVerifier.sol";
138 | | import "../../contracts/mock/ReferralStorage.sol";
139 | | import "../../contracts/mock/Multicall3.sol";
140 | | import "../mocks/ChainlinkMock.sol";
141 | | import "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
142 | |
143 | | //Gov
144 | | import "../../contracts/gov/GovTimelockController.sol";
145 | | import "../../contracts/gov/GovToken.sol";
146 | | import "../../contracts/gov/ProtocolGovernor.sol";
147 | |
148 | | //Events
149 | | import "../../contracts/event/EventEmitter.sol";
150 | |
151 | | // Oracle
152 | | import "../../contracts/oracle/OracleStore.sol";
153 | | import "../../contracts/oracle/GmOracleProvider.sol";
154 | | import "../../contracts/oracle/ChainlinkPriceFeedProvider.sol";
155 | | import "../../contracts/oracle/Oracle.sol";
156 | | import "../../contracts/oracle/ChainlinkDataStreamProvider.sol";
157 | |
158 | | //Order
159 | | import "../../contracts/order/OrderVault.sol";
160 | |
161 | | //Market
162 | | import "../../contracts/market/MarketFactory.sol";
163 | |
164 | | //Swap
165 | | import "../../contracts/swap/SwapHandler.sol";
166 | |
167 | | //Exchange
168 | | import "../../contracts/exchange/AdlHandler.sol";
169 | | import "../../contracts/exchange/DepositHandler.sol";
170 | | import "../../contracts/exchange/WithdrawalHandler.sol";
171 | | import "../../contracts/exchange/ShiftHandler.sol";
172 | | import "../../contracts/exchange/OrderHandler.sol";
173 | | import "../../contracts/exchange/LiquidationHandler.sol";
174 | |
175 | | //External
176 | | import "../../contracts/external/ExternalHandler.sol";
177 | |
178 | | //Callback
179 | | // import "../../contracts/callback/CallbackUtils.sol";
180 | |
181 | | //Chain
182 | | // import "../../contracts/chain/ChainReader.sol";
183 | |
184 | | //Config
185 | | import "../../contracts/config/Config.sol";
186 | |
187 | | //Deposit
188 | | import "../../contracts/deposit/DepositEventUtils.sol";
189 | | import "../../contracts/deposit/DepositVault.sol";
190 | | import "../../contracts/deposit/DepositStoreUtils.sol";
191 | | import "../../contracts/deposit/DepositUtils.sol";
192 | | // import "../../contracts/deposit/ExecuteDepositUtils.sol";
193 | |
194 | | //Router
195 | | import "../../contracts/router/Router.sol";
196 | | import "../../contracts/router/ExchangeRouter.sol";
197 | | import "../../contracts/router/SubaccountRouter.sol";
198 | |
199 | | //Withdrawal
200 | | import "../../contracts/withdrawal/WithdrawalVault.sol";
201 | | import "../../contracts/withdrawal/WithdrawalStoreUtils.sol";
202 | | import "../../contracts/withdrawal/WithdrawalEventUtils.sol";
203 | | import "../../contracts/withdrawal/WithdrawalUtils.sol";
204 | | // import "../../contracts/withdrawal/ExecuteWithdrawalUtils.sol";
205 | |
206 | | //Shift
207 | | // import "../../contracts/Shift/ShiftVault.sol";
208 | | // import "../../contracts/Shift/ShiftStoreUtils.sol";
209 | | // import "../../contracts/Shift/ShiftEventUtils.sol";
210 | | // import "../../contracts/Shift/ShiftUtils.sol";
211 | | // import "../../contracts/Shift/Shift.sol";
212 | |
213 | | //Referral
214 | | import "../../contracts/referral/ReferralUtils.sol";
215 | |
216 | | //Fee
217 | | import "../../contracts/fee/FeeHandler.sol";
218 | |
219 | | //Liquidations
220 | | import "../../contracts/liquidation/LiquidationUtils.sol";
221 | |
222 | | //Reader
223 | | import "../../contracts/reader/ReaderPricingUtils.sol";
224 | | import "../../contracts/reader/ReaderUtils.sol";
225 | | import "../../contracts/reader/ReaderDepositUtils.sol";
226 | | import "../../contracts/reader/ReaderWithdrawalUtils.sol";
227 | | import "../../contracts/reader/Reader.sol";
228 | |
229 | | //Timelock
230 | | import "../../contracts/config/Timelock.sol";
231 | |
232 | | //Migration
233 | | import "../../contracts/migration/TimestampInitializer.sol";
234 | |
235 | | //Callback contract
236 | | import "./GasFeeCallbackReceiver.sol";
237 | |
238 | | //Gamma
239 | |
240 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
241 | | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
242 | | import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
243 | | import {PerpetualVault} from "../../../../contracts/PerpetualVault.sol";
244 | | import {MockGmxUtils as GmxUtils} from "../../../mock/MockGMXUtils.sol";
245 | | import {KeeperProxy} from "../../../../contracts/KeeperProxy.sol";
246 | | import {MarketPrices, PriceProps} from "../../../../contracts/libraries/StructData.sol";
247 | | import {MockData} from "../../../mock/MockData.sol";
248 | | import {PerpetualVaultLens} from "../../../../contracts/PerpetualVaultLens.sol";
249 | |
250 | | //MOCK DEX
251 | |
252 | | import {MockDex} from "../mocks/MockDEX.sol";
253 | |
254 | | /**
255 | | *
256 | | *
257 | | *
258 | | *
259 | | */
260 | | contract FuzzStorageVars is FuzzGMXConfig {
261 | | //Role
262 | | RoleStore internal roleStore;
263 | |
264 | | //Data
265 | | DataStore internal dataStore;
266 | |
267 | | //Mocks
268 | | WNT internal WETH;
269 | | MintableToken internal WBTC;
270 | | MintableToken internal USDC;
271 | | MintableToken internal USDT;
272 | | MockPriceFeed internal USDCPriceFeed;
273 | | MockPriceFeed internal USDTPriceFeed;
274 | | MockPriceFeed internal mockPriceFeed;
275 | | MockDataStreamVerifier internal mockDataStreamVerifier;
276 | | ReferralStorage internal referralStorage;
277 | | Multicall3 internal multicall3;
278 | | AggregatorV2V3Interface internal aggregatorV2V3Interface; //for eventual future deployment, currently address 0 in Oralcle setup
279 | |
280 | | //Gov
281 | | GovTimelockController internal govTimelockController;
282 | | GovToken internal govToken;
283 | | ProtocolGovernor internal protocolGovernor;
284 | |
285 | | //Events
286 | | EventEmitter internal eventEmitter;
287 | |
288 | | //Oracles
289 | | OracleStore internal oracleStore;
290 | | GmOracleProvider internal gmOracleProvider;
291 | | ChainlinkPriceFeedProvider internal chainlinkPriceFeedProvider;
292 | | Oracle internal oracle;
293 | | ChainlinkDataStreamProvider internal chainlinkDataStreamProvider;
294 | | ChainlinkMock internal chainlinkMock;
295 | |
296 | | //Order
297 | | OrderVault internal orderVault;
298 | |
299 | | //Market
300 | | MarketFactory internal marketFactory;
301 | |
302 | | //Swap
303 | | SwapHandler internal swapHandler;
304 | |
305 | | //Exchange
306 | | AdlHandler internal adlHandler;
307 | | DepositHandler internal depositHandler;
308 | | WithdrawalHandler internal withdrawalHandler;
309 | | ShiftHandler internal shiftHandler;
310 | | OrderHandler internal orderHandler;
311 | | LiquidationHandler internal liquidationHandler;
312 | |
313 | | //External
314 | | ExternalHandler internal externalHandler;
315 | |
316 | | //Config
317 | | Config internal config;
318 | |
319 | | //Deposit
320 | | DepositVault internal depositVault;
321 | |
322 | | //Router
323 | | Router internal router;
324 | | ExchangeRouter internal exchangeRouter;
325 | | SubaccountRouter internal subaccountRouter;
326 | |
327 | | //Withdrawal
328 | | WithdrawalVault internal withdrawalVault;
329 | |
330 | | //Shift
331 | | ShiftVault internal shiftVault;
332 | | // ShiftStoreUtils internal shiftStoreUtils;
333 | | // ShiftEventUtils internal shiftEventUtils;
334 | | // ShiftUtils internal shiftUtils;
335 | |
336 | | //Fee
337 | | FeeHandler internal feeHandler;
338 | |
339 | | //Reader
340 | |
341 | | Reader internal reader;
342 | |
343 | | //Timelock
344 | | Timelock internal timelock;
345 | |
346 | | //Migration
347 | | TimestampInitializer internal timestampInitializer;
348 | |
349 | | /**
350 | | * 0_0 *
351 | | * --- MARKETS ---
352 | | */
353 | | address market_WETH_WETH_USDC;
354 | | address market_WETH_WETH_USDT;
355 | | address market_0_WETH_USDC;
356 | | address market_WBTC_WBTC_USDC;
357 | |
358 | | /**
359 | | * 0_0 *
360 | | * --- CALLBACKS ---
361 | | */
362 | |
363 | | GasFeeCallbackReceiver internal callback;
364 | |
365 | | /**
366 | | * 0_0 *
367 | | * --- GAMMA ---
368 | | */
369 | * | mapping(address => address) public vaultToMarket;
370 | |
371 | * | ProxyAdmin public proxyAdmin;
372 | |
373 | * | GmxUtils public gmxUtilsLogic_GammaVault1x_WETHUSDC;
374 | * | GmxUtils public gmxUtilsLogic_GammaVault2x_WETHUSDC;
375 | * | GmxUtils public gmxUtilsLogic_GammaVault3x_WETHUSDC;
376 | |
377 | | // PerpetualVault public perpetualVault_GammaVaul1x_WETHUSDC;
378 | | // PerpetualVault public perpetualVault_GammaVaul2x_WETHUSDC;
379 | | // PerpetualVault public perpetualVault_GammaVault3x_WETHUSDC; //NOTE: using lens
380 | |
381 | * | PerpetualVaultLens public perpetualVault_GammaVault1x_WETHUSDC;
382 | * | PerpetualVaultLens public perpetualVault_GammaVault2x_WETHUSDC;
383 | * | PerpetualVaultLens public perpetualVault_GammaVault3x_WETHUSDC;
384 | |
385 | | address gmxUtils_GammaVault1x_WETHUSDC;
386 | | address gmxUtils_GammaVault2x_WETHUSDC;
387 | | address gmxUtils_GammaVault3x_WETHUSDC;
388 | | address payable vault_GammaVault1x_WETHUSDC;
389 | | address payable vault_GammaVault2x_WETHUSDC;
390 | | address payable vault_GammaVault3x_WETHUSDC;
391 | |
392 | * | GmxUtils public gmxUtilsLogic_GammaVault1x_WBTCUSDC;
393 | * | GmxUtils public gmxUtilsLogic_GammaVault2x_WBTCUSDC;
394 | * | GmxUtils public gmxUtilsLogic_GammaVault3x_WBTCUSDC;
395 | |
396 | * | PerpetualVaultLens public perpetualVault_GammaVaul1x_WBTCUSDC;
397 | * | PerpetualVaultLens public perpetualVault_GammaVault2x_WBTCUSDC;
398 | * | PerpetualVaultLens public perpetualVault_GammaVault3x_WBTCUSDC;
399 | |
400 | | // PerpetualVault public perpetualVault_GammaVaul1x_WBTCUSDC;
401 | | // PerpetualVault public perpetualVault_GammaVault2x_WBTCUSDC;
402 | | // PerpetualVault public perpetualVault_GammaVault3x_WBTCUSDC;
403 | |
404 | | address gmxUtils_GammaVault1x_WBTCUSDC;
405 | | address gmxUtils_GammaVault2x_WBTCUSDC;
406 | | address gmxUtils_GammaVault3x_WBTCUSDC;
407 | |
408 | | address payable vault_GammaVault1x_WBTCUSDC;
409 | | address payable vault_GammaVault2x_WBTCUSDC;
410 | | address payable vault_GammaVault3x_WBTCUSDC;
411 | |
412 | | address[6] internal VAULTS;
413 | |
414 | * | MockData public mockData;
415 | | /**
416 | | * 0_0 *
417 | | * --- DEX Mock ---
418 | | */
419 | |
420 | * | MockDex public mockDex;
421 | | address PARASWAP_ROUTER;
422 | |
423 | | bool DEBUG = true;
424 | | }
425 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/GasFeeCallbackReceiver.sol
1 | | // SPDX-License-Identifier: BUSL-1.1
2 | |
3 | | pragma solidity ^0.8.0;
4 | | import "fuzzlib/FuzzBase.sol";
5 | |
6 | | import "../../contracts/event/EventUtils.sol";
7 | | import "../../contracts/deposit/Deposit.sol";
8 | | import "../../contracts/withdrawal/Withdrawal.sol";
9 | | import "../../contracts/shift/Shift.sol";
10 | | import "../../contracts/order/Order.sol";
11 | |
12 | * | contract GasFeeCallbackReceiver is FuzzBase {
13 | * | function refundExecutionFee(
14 | | bytes32 key,
15 | | EventUtils.EventLogData memory eventData
16 | | ) public payable {}
17 | |
18 | * | function afterDepositExecution(
19 | | bytes32 key,
20 | | Deposit.Props memory deposit,
21 | | EventUtils.EventLogData memory eventData
22 | | ) public payable {}
23 | |
24 | * | function afterDepositCancellation(
25 | | bytes32 key,
26 | | Deposit.Props memory deposit,
27 | | EventUtils.EventLogData memory eventData
28 | | ) public payable {}
29 | |
30 | | function afterWithdrawalExecution(
31 | | bytes32 key,
32 | | Withdrawal.Props memory withdrawal,
33 | | EventUtils.EventLogData memory eventData
34 | | ) public payable {}
35 | |
36 | | function afterWithdrawalCancellation(
37 | | bytes32 key,
38 | | Withdrawal.Props memory withdrawal,
39 | | EventUtils.EventLogData memory eventData
40 | | ) public payable {}
41 | |
42 | | function afterShiftExecution(
43 | | bytes32 key,
44 | | Shift.Props memory shift,
45 | | EventUtils.EventLogData memory eventData
46 | | ) public payable {}
47 | |
48 | | function afterShiftCancellation(
49 | | bytes32 key,
50 | | Shift.Props memory shift,
51 | | EventUtils.EventLogData memory eventData
52 | | ) public payable {}
53 | |
54 | * | function afterOrderExecution(
55 | | bytes32 key,
56 | | Order.Props memory order,
57 | | EventUtils.EventLogData memory eventData
58 | | ) public payable {}
59 | |
60 | * | function afterOrderCancellation(
61 | | bytes32 key,
62 | | Order.Props memory order,
63 | | EventUtils.EventLogData memory eventData
64 | | ) public payable {}
65 | |
66 | * | function afterOrderFrozen(
67 | | bytes32 key,
68 | | Order.Props memory order,
69 | | EventUtils.EventLogData memory eventData
70 | | ) public payable {}
71 | |
72 | * | function cleanETHBalance(address user) public {
73 | * | address(user).call{value: address(this).balance}("");
74 | | }
75 | |
76 | | receive() external payable {}
77 | | }
78 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FunctionCalls.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | | import "../setup/FuzzStorageVars.sol";
5 | | import "fuzzlib/FuzzBase.sol";
6 | | import {Test, console2} from "forge-std/Test.sol";
7 | | import {IHevm} from "fuzzlib/IHevm.sol";
8 | |
9 | | abstract contract FunctionCalls is FuzzStorageVars, FuzzBase, Test {
10 | | // IHevm internal hevm = IHevm(address(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)); //workaround for direct prank call
11 | |
12 | | //Events
13 | | event RoleChangingCall(
14 | | address caller,
15 | | address grantedTo,
16 | | bytes32 role,
17 | | bool success
18 | | );
19 | | event OracleSignerAdded(address caller, address addedSigner, bool success);
20 | | event SetUintDataStoreCall(
21 | | address caller,
22 | | bytes32 key,
23 | | uint256 value,
24 | | bool success
25 | | );
26 | | event SetBoolDataStoreCall(
27 | | address caller,
28 | | bytes32 key,
29 | | bool value,
30 | | bool success
31 | | );
32 | | event SetBytes32DataStoreCall(
33 | | address caller,
34 | | bytes32 key,
35 | | bytes32 value,
36 | | bool success
37 | | );
38 | | event SetAddressDataStoreCall(
39 | | address caller,
40 | | bytes32 key,
41 | | address addressTo,
42 | | bool success
43 | | );
44 | |
45 | | error dataWriteError();
46 | |
47 | | // GAMMA Functions
48 | |
49 | * | function _gamma_DepositCall(
50 | | address user,
51 | | address vault,
52 | | uint256 amount,
53 | | uint256 executionFee
54 | * | ) internal returns (bool success, bytes memory returnData) {
55 | * | bytes memory data = abi.encodeWithSelector(
56 | * | PerpetualVaultLens.deposit.selector,
57 | * | amount
58 | | );
59 | |
60 | * | uint256 value = executionFee * tx.gasprice;
61 | * | vm.prank(user);
62 | * | (success, returnData) = vault.call{value: value}(data);
63 | | }
64 | |
65 | * | function _gamma_CanceDepositCall(
66 | | address vault,
67 | | address gammaKeeper
68 | * | ) internal returns (bool success, bytes memory returnData) {
69 | * | bytes memory data = abi.encodeWithSelector(
70 | * | PerpetualVault.cancelDeposit.selector
71 | | );
72 | |
73 | * | vm.prank(gammaKeeper);
74 | * | (success, returnData) = vault.call(data);
75 | | }
76 | |
77 | * | function _gamma_WithdrawCall(
78 | | address user,
79 | | address vault,
80 | | uint256 depositId,
81 | | uint256 executionFee
82 | * | ) internal returns (bool success, bytes memory returnData) {
83 | * | bytes memory data = abi.encodeWithSelector(
84 | * | PerpetualVaultLens.withdraw.selector,
85 | * | user,
86 | * | depositId
87 | | );
88 | |
89 | * | uint256 value = (executionFee * tx.gasprice) * 2; //NOTE: 2 executions
90 | * | vm.prank(user);
91 | * | (success, returnData) = vault.call{value: value}(data);
92 | | }
93 | |
94 | | // GMX Functions
95 | | function _roleChangingCall(
96 | | address caller,
97 | | address to,
98 | | bytes32 role
99 | | ) internal returns (bool success, bytes memory returnData) {
100 | | vm.prank(caller);
101 | | (success, returnData) = address(roleStore).call{gas: 1000000}(
102 | | abi.encodeWithSelector(RoleStore.grantRole.selector, to, role)
103 | | );
104 | | if (!success) {
105 | | revert dataWriteError();
106 | | }
107 | | emit RoleChangingCall(caller, to, role, success);
108 | | }
109 | |
110 | | function _oracleAddSignerCall(
111 | | address controller,
112 | | address to
113 | | ) internal returns (bool success, bytes memory returnData) {
114 | | vm.prank(controller);
115 | | (success, returnData) = address(oracleStore).call{gas: 1000000}(
116 | | abi.encodeWithSelector(OracleStore.addSigner.selector, to)
117 | | );
118 | | if (!success) {
119 | | revert dataWriteError();
120 | | }
121 | | emit OracleSignerAdded(controller, to, success);
122 | | }
123 | |
124 | | function _setUintDataStoreCall(
125 | | address caller,
126 | | string memory key,
127 | | uint256 value,
128 | | address addedAddress
129 | | ) internal returns (bool success, bytes memory returnData) {
130 | | bytes32 hashedKey;
131 | | if (addedAddress != address(0)) {
132 | | hashedKey = keccak256(
133 | | abi.encode(keccak256(abi.encode(key)), addedAddress)
134 | | );
135 | | } else {
136 | | hashedKey = keccak256(abi.encode(key));
137 | | }
138 | | vm.prank(caller);
139 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
140 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value)
141 | | );
142 | | if (!success) {
143 | | revert dataWriteError();
144 | | }
145 | | emit SetUintDataStoreCall(caller, hashedKey, value, success);
146 | | }
147 | |
148 | | function _setUintDataStoreCall(
149 | | address caller,
150 | | string memory key,
151 | | uint256 value,
152 | | address addr1,
153 | | address addr2
154 | | ) internal returns (bool success, bytes memory returnData) {
155 | | bytes32 hashedKey;
156 | | hashedKey = _hashData(key, addr1, addr2);
157 | |
158 | | vm.prank(caller);
159 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
160 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value)
161 | | );
162 | | if (!success) {
163 | | revert dataWriteError();
164 | | }
165 | | emit SetUintDataStoreCall(caller, hashedKey, value, success);
166 | | }
167 | |
168 | | function _setUintDataStoreCall(
169 | | address caller,
170 | | string memory key,
171 | | uint256 value,
172 | | address addr1,
173 | | bool addedBool
174 | | ) internal returns (bool success, bytes memory returnData) {
175 | | bytes32 hashedKey;
176 | | hashedKey = _hashData(key, addr1, addedBool);
177 | |
178 | | vm.prank(caller);
179 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
180 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value)
181 | | );
182 | | if (!success) {
183 | | revert dataWriteError();
184 | | }
185 | | emit SetUintDataStoreCall(caller, hashedKey, value, success);
186 | | }
187 | |
188 | | function _setUintWithBoolDataStoreCall(
189 | | address caller,
190 | | string memory key,
191 | | uint256 value,
192 | | bool addedBool
193 | | ) internal returns (bool success, bytes memory returnData) {
194 | | bytes32 hashedKey = keccak256(
195 | | abi.encode(keccak256(abi.encode(key)), addedBool)
196 | | );
197 | |
198 | | vm.prank(caller);
199 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
200 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value)
201 | | );
202 | | if (!success) {
203 | | revert dataWriteError();
204 | | }
205 | | emit SetUintDataStoreCall(caller, hashedKey, value, success);
206 | | }
207 | |
208 | | function _setAddressDataStoreCall(
209 | | address caller,
210 | | string memory key,
211 | | address addressAsValue,
212 | | address addedAddress
213 | | ) internal returns (bool success, bytes memory returnData) {
214 | | bytes32 hashedKey;
215 | | if (addedAddress != address(0)) {
216 | | hashedKey = keccak256(
217 | | abi.encode(keccak256(abi.encode(key)), addedAddress)
218 | | );
219 | | } else {
220 | | hashedKey = keccak256(abi.encode(key));
221 | | }
222 | | vm.prank(caller);
223 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
224 | | abi.encodeWithSelector(
225 | | DataStore.setAddress.selector,
226 | | hashedKey,
227 | | addressAsValue
228 | | )
229 | | );
230 | | if (!success) {
231 | | revert dataWriteError();
232 | | }
233 | | emit SetAddressDataStoreCall(
234 | | caller,
235 | | hashedKey,
236 | | addressAsValue,
237 | | success
238 | | );
239 | | }
240 | |
241 | | function _setUintDataStoreCall(
242 | | address caller,
243 | | string memory string1,
244 | | string memory string2,
245 | | uint256 value,
246 | | address market,
247 | | bool isLong
248 | | ) internal returns (bool success, bytes memory returnData) {
249 | | bytes32 hashedString1 = keccak256(abi.encode(string1));
250 | |
251 | | bytes32 hashedKey = keccak256(
252 | | abi.encode(
253 | | hashedString1,
254 | | keccak256(abi.encode(string2)),
255 | | market,
256 | | isLong
257 | | )
258 | | );
259 | |
260 | | vm.prank(caller);
261 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
262 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value)
263 | | );
264 | | if (!success) {
265 | | revert dataWriteError();
266 | | }
267 | | emit SetUintDataStoreCall(caller, hashedKey, value, success);
268 | | }
269 | |
270 | | function _setBoolDataStoreCall(
271 | | address caller,
272 | | string memory key,
273 | | bool value,
274 | | address addedAddress
275 | | ) internal returns (bool success, bytes memory returnData) {
276 | | bytes32 hashedKey;
277 | | if (addedAddress != address(0)) {
278 | | hashedKey = keccak256(
279 | | abi.encode(keccak256(abi.encode(key)), addedAddress)
280 | | );
281 | | } else {
282 | | hashedKey = keccak256(abi.encode(key));
283 | | }
284 | |
285 | | vm.prank(caller);
286 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
287 | | abi.encodeWithSelector(DataStore.setBool.selector, hashedKey, value)
288 | | );
289 | | if (!success) {
290 | | revert dataWriteError();
291 | | }
292 | | emit SetBoolDataStoreCall(caller, hashedKey, value, success);
293 | | }
294 | |
295 | | function _setBytes32DataStoreCall(
296 | | address caller,
297 | | string memory key,
298 | | address addedAddress,
299 | | bytes32 value
300 | | ) internal returns (bool success, bytes memory returnData) {
301 | | bytes32 hashedKey;
302 | | hashedKey = keccak256(
303 | | abi.encode(keccak256(abi.encode(key)), addedAddress)
304 | | );
305 | |
306 | | vm.prank(caller);
307 | | (success, returnData) = address(dataStore).call{gas: 1000000}(
308 | | abi.encodeWithSelector(
309 | | DataStore.setBytes32.selector,
310 | | hashedKey,
311 | | value
312 | | )
313 | | );
314 | | if (!success) {
315 | | revert dataWriteError();
316 | | }
317 | | emit SetBytes32DataStoreCall(caller, hashedKey, value, success);
318 | | }
319 | | }
320 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FuzzActors.sol
1 | | // SPDX-License-Identifier: MIT
2 | |
3 | | pragma solidity ^0.8.0;
4 | |
5 | | import "./FunctionCalls.sol";
6 | |
7 | | contract FuzzActors is FunctionCalls {
8 | | address internal DEPLOYER;
9 | | address internal HEVM_INITIAL_ADDRESS =
10 | | address(0x00a329c0648769A73afAc7F9381E08FB43dBEA72);
11 | | address internal FOUNDRY_INITIAL_ADDRESS =
12 | | address(0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496);
13 | | address internal FOUNDRY_DEFAULT_ADDRESS =
14 | | 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
15 | |
16 | | address internal gammaKeeper = address(0xeeefeee);
17 | |
18 | | address payable internal treasury_GammaVault1x_WETHUSDC =
19 | | payable(address(0xea1));
20 | | address payable internal treasury_GammaVault2x_WETHUSDC =
21 | | payable(address(0xea2));
22 | | address payable internal treasury_GammaVault3x_WETHUSDC =
23 | | payable(address(0xea3));
24 | |
25 | | address payable internal treasury_GammaVault1x_WBTCUSDC =
26 | | payable(address(0xea1));
27 | | address payable internal treasury_GammaVault2x_WBTCUSDC =
28 | | payable(address(0xea2));
29 | | address payable internal treasury_GammaVault3x_WBTCUSDC =
30 | | payable(address(0xea3));
31 | |
32 | | address internal paraswapDeployer =
33 | | address(0xf01121e808F782d7F34E857c27dA31AD1f151b39);
34 | |
35 | | address internal USER0 = address(10101);
36 | | address internal USER1 = address(1);
37 | | address internal USER2 = address(2);
38 | | address internal USER3 = address(3);
39 | | address internal USER4 = address(4);
40 | | address internal USER5 = address(5);
41 | | address internal USER6 = address(6);
42 | | address internal USER7 = address(7);
43 | | address internal USER8 = address(8);
44 | | address internal USER9 = address(9);
45 | | address internal USER10 = address(10);
46 | | address internal USER11 = address(11);
47 | | address internal USER12 = address(12);
48 | | address internal USER13 = address(13);
49 | |
50 | | address[] internal USERS = [
51 | | USER0,
52 | | USER1,
53 | | USER2,
54 | | USER3,
55 | | USER4,
56 | | USER5,
57 | | USER6,
58 | | USER7,
59 | | USER8,
60 | | USER9,
61 | | USER10,
62 | | USER11,
63 | | USER12,
64 | | USER13
65 | | ];
66 | | }
67 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FuzzUtils.sol
1 | | // SPDX-License-Identifier: MIT
2 | | pragma solidity ^0.8.0;
3 | |
4 | * | contract FuzzUtils {
5 | | function _getSyntheticTokenAddress(string memory tokenSymbol) internal view returns (address) {
6 | | uint256 chainId = block.chainid;
7 | | bytes32 hashedData = keccak256(abi.encode(chainId, tokenSymbol));
8 | | bytes20 addressBytes = bytes20(hashedData << 96);
9 | | return address(addressBytes);
10 | | }
11 | |
12 | | function _hashData(
13 | | string memory key,
14 | | address address1,
15 | | address address2
16 | | ) internal pure returns (bytes32) {
17 | | bytes32 hashedKey = keccak256(abi.encode(keccak256(abi.encode(key)), address1, address2));
18 | | return hashedKey;
19 | | }
20 | |
21 | | function _hashData(
22 | | string memory key,
23 | | address address1,
24 | | bool addedBool
25 | | ) internal pure returns (bytes32) {
26 | | bytes32 hashedKey = keccak256(abi.encode(keccak256(abi.encode(key)), address1, addedBool));
27 | | return hashedKey;
28 | | }
29 | | }
30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/mock/MockData.sol
1 | | // SPDX-License-Identifier: UNLICENSED
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import {Test, console} from "forge-std/Test.sol";
5 | | import {MarketPrices, PriceProps} from "../../contracts/libraries/StructData.sol";
6 | |
7 | * | contract MockData {
8 | | struct OracleSetPriceParams {
9 | | address[] tokens;
10 | | address[] providers;
11 | | bytes[] data;
12 | | }
13 | |
14 | | function getMarketPrices()
15 | | external
16 | | pure
17 | | returns (MarketPrices memory marketPrices)
18 | | {
19 | | marketPrices.indexTokenPrice = PriceProps({
20 | | min: 3419847300000000,
21 | | max: 3419869700000000
22 | | });
23 | | marketPrices.longTokenPrice = PriceProps({
24 | | min: 3419847300000000,
25 | | max: 3419869700000000
26 | | });
27 | | marketPrices.shortTokenPrice = PriceProps({
28 | | min: 999950180000000000000000,
29 | | max: 1000024800000000000000000
30 | | });
31 | | }
32 | |
33 | | function getOraclePrices() external pure returns (PriceProps[] memory) {
34 | | PriceProps[] memory prices = new PriceProps[](2);
35 | | prices[0] = PriceProps({min: 3419847300000000, max: 3419869700000000});
36 | | prices[1] = PriceProps({
37 | | min: 999950180000000000000000,
38 | | max: 1000024800000000000000000
39 | | });
40 | |
41 | | return prices;
42 | | }
43 | |
44 | | function getOracleParams()
45 | | external
46 | | pure
47 | | returns (OracleSetPriceParams memory params)
48 | | {
49 | | params.tokens = new address[](2);
50 | | params.tokens[0] = address(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);
51 | | params.tokens[1] = address(0xaf88d065e77c8cC2239327C5EDb3A432268e5831);
52 | | params.providers = new address[](2);
53 | | params.providers[0] = address(
54 | | 0x83cBb05AA78014305194450c4AADAc887fe5DF7F
55 | | );
56 | | params.providers[1] = address(
57 | | 0x83cBb05AA78014305194450c4AADAc887fe5DF7F
58 | | );
59 | | params.data = new bytes[](2);
60 | | params.data[
61 | | 0
62 | | ] = hex"0006f100c86a0007ed73322d6e26606c9985fd511be9d92cf5af6b3dda8143c7000000000000000000000000000000000000000000000000000000000ae8e50a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000100010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae900000000000000000000000000000000000000000000000000000000669949e600000000000000000000000000000000000000000000000000000000669949e60000000000000000000000000000000000000000000000000000551d78bf0938000000000000000000000000000000000000000000000000005322d2ac29a26c00000000000000000000000000000000000000000000000000000000669a9b660000000000000000000000000000000000000000000000b95cff9c1026ae40000000000000000000000000000000000000000000000000b95c4df953f7e940000000000000000000000000000000000000000000000000b95db199bf65ed80000000000000000000000000000000000000000000000000000000000000000006d18dc8df172f8ff7e170ba49dcb29f43a15f93cdef2b7f1d0ae3b82ab13caac2325d14bb01fff320f57dda003397bdae87eb799ed6a7ba9a627e1977432739e37df4c18b224a5408d7d60d20028188b6569db49a3df91fa6ae6674fccb8768c27f23bad9cdcb616e035c64b1b5cb06bd2d1141d4103cac01f4cf5e15c32a24b4b3cdd3ccfee8a3ea58c715efd1dea13d5bbdae658ba3d69215002dbf1af6d0a108928a08795e3e217919d1545db34859e667b246b608413a97b4863d4678100800000000000000000000000000000000000000000000000000000000000000065cc304c8f052759efe955ff541920728a157dd7cf0a7d8ab609523b8a35d85bd617bd1fa6537d8e7e483354be180502a6dcd3b60a8591dd33112ca643e3eaa5c1723fecccb473f16e6247a38c252968d9565c88dad115c964efc2062525655615eff0d54067a12e235d0967472ceda0486a5167e03334f44fcf0fc8f3a5c0cbe512d6582e44bcff0b3192e379df3bf81ab13c314e687e06dd772151ffac8811646d53f3cea69dcb73b1c727fb662502528bf238580d367fbd34e12c8fcf2d509";
63 | | params.data[
64 | | 1
65 | | ] = hex"00064c28ccf99cc505d648ffcbc4c2c613859826fd4552841a6822b51800d961000000000000000000000000000000000000000000000000000000000ac42e17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000001010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000038f83323b6b08116d1614cf33a9bd71ab5e0abf0c9f1b783a74a43e7bd99200000000000000000000000000000000000000000000000000000000669949e600000000000000000000000000000000000000000000000000000000669949e60000000000000000000000000000000000000000000000000000551edd373de4000000000000000000000000000000000000000000000000005322d2ac29a26c00000000000000000000000000000000000000000000000000000000669a9b660000000000000000000000000000000000000000000000000de0bf578b8418000000000000000000000000000000000000000000000000000de0af043c246c000000000000000000000000000000000000000000000000000de0cfb67f1f38000000000000000000000000000000000000000000000000000000000000000006176fdcbe9c1717344c64be7e30d543a72ec9960b275b4c064a90432e8408dfc3bd436a7c8d6b1041b935369da8accf79883d6ad5926e26f589b0f4962e2e6e9055ee71b93883799865de7863a1a336864cd6e0399a4129dd743f9ede31fb71c3e0f4b056e12177458c94b5e3dc36e93fd47f1f4deefa16bd8ba1d200217fe7089e2599c205dea1b83f069266d3d8290d598654a4a01f9a307fcac5d94cc826c5e2e7e0470b9606c8ff79cda41a8cfca602e25330f14233e7c2d65bfab64fd50b000000000000000000000000000000000000000000000000000000000000000657989c03317218d871a6e5cc59bec63fa4793b007a20f56adacfac96d55f206f19fb8653cf4de2b7831032f01175b648a24d315197bb00991383395f38d7694126f4dc31b1df1f8139958ba2df47db457d1ac573a59c1223235de884074aa3c7687b072a819066ca90f206af10e95218d04afe9d79fdbdaba50759113bfd142d176774fffe4f0db45768c67e8f08ca2f82b6acfabd5abe5475153f4dbba4140c3350982bc21338060ff64137dfdf231cfa25d35ae829ccaa983adfa2a1f26a67";
66 | | }
67 | |
68 | | function getParaSwapData(
69 | | address receiver
70 | | ) external pure returns (bytes memory) {
71 | | bytes memory rev = abi.encodePacked(receiver);
72 | | bytes
73 | | memory original = hex"000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5700000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000056446c67b6d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000286524c9166933d300000000000000000000000000000000000000000000000028991bf71f8751ac00000000000000000000000005c05fc1acf6a113b2235117a5264252d61383cd00000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000066994b15cfa2c4a6f06f493098741ef2682cf0fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000369a2fdb910d432f0a07381a5e3d27572c876713000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000066a2845e0000000000000000000000000000000000000000000000000000000000000042af88d065e77c8cc2239327c5edb3a432268e58310001f42f2a2543b76a4166549f7aab2e75bef0aefc5b0f0001f482af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
74 | |
75 | | bytes memory result = original;
76 | |
77 | | assembly {
78 | | let originalPtr := add(result, 0x20)
79 | | let replacementPtr := add(rev, 0x20)
80 | |
81 | | for {
82 | | let i := 0
83 | | } lt(i, mload(rev)) {
84 | | i := add(i, 0x20)
85 | | } {
86 | | mstore(
87 | | add(originalPtr, add(304, i)),
88 | | mload(add(replacementPtr, i))
89 | | )
90 | | }
91 | | }
92 | | require(original.length == result.length, "fail");
93 | | return result;
94 | | }
95 | | }
96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/mock/MockGMXUtils.sol
1 | | // SPDX-License-Identifier: GPL-3.0-only
2 | | pragma solidity ^0.8.4;
3 | |
4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
7 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
8 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol";
9 | |
10 | | import "../../contracts/libraries/Position.sol";
11 | | import "../../contracts/libraries/Order.sol";
12 | | import "../../contracts/libraries/gmx/MarketUtils.sol";
13 | | import "../../contracts/interfaces/gmx/IDataStore.sol";
14 | | import "../../contracts/interfaces/gmx/IReader.sol";
15 | | import "../../contracts/interfaces/gmx/IOrderHandler.sol";
16 | | import "../../contracts/interfaces/gmx/IOrderCallbackReceiver.sol";
17 | | import "../../contracts/interfaces/IPerpetualVault.sol";
18 | | import "../../contracts/interfaces/gmx/IExchangeRouter.sol";
19 | | import "../../contracts/interfaces/IGmxUtils.sol";
20 | | import {Test, console} from "forge-std/Test.sol";
21 | |
22 | | /**
23 | | * @title GMXUtils
24 | | * @dev Contract for Interaction with GMX.
25 | | * this contract is not a library and is not recommended for several perpetual vaults to share a GMXUtils contract
26 | | * We should create one GMXUtils instance for one perpertual vault because all GMX positions are
27 | | * registered as GMXUtils address in GMX protocol
28 | | */
29 | |
30 | * | contract MockGmxUtils is
31 | | IOrderCallbackReceiver,
32 | | Initializable,
33 | | Ownable2StepUpgradeable
34 | | {
35 | | using SafeERC20 for IERC20;
36 | |
37 | | using SafeCast for uint256;
38 | |
39 | | using Position for Position.Props;
40 | |
41 | | struct PositionData {
42 | | uint256 sizeInUsd;
43 | | uint256 sizeInTokens;
44 | | uint256 collateralAmount;
45 | | uint256 netValue;
46 | | bool isLong;
47 | | }
48 | |
49 | | struct OrderQueue {
50 | | bytes32 requestKey;
51 | | address tokenIn;
52 | | uint256 amountIn;
53 | | bool isSettle;
54 | | }
55 | |
56 | | bytes32 public constant COLLATERAL_TOKEN =
57 | | keccak256(abi.encode("COLLATERAL_TOKEN"));
58 | |
59 | * | bytes32 public constant SIZE_IN_USD = keccak256(abi.encode("SIZE_IN_USD"));
60 | |
61 | | bytes32 public constant SIZE_IN_TOKENS =
62 | | keccak256(abi.encode("SIZE_IN_TOKENS"));
63 | |
64 | | bytes32 public constant COLLATERAL_AMOUNT =
65 | | keccak256(abi.encode("COLLATERAL_AMOUNT"));
66 | |
67 | | bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 =
68 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1"));
69 | |
70 | | bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE =
71 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE"));
72 | |
73 | | bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR =
74 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR"));
75 | |
76 | | bytes32 public constant INCREASE_ORDER_GAS_LIMIT =
77 | * | keccak256(abi.encode("INCREASE_ORDER_GAS_LIMIT"));
78 | |
79 | | bytes32 public constant DECREASE_ORDER_GAS_LIMIT =
80 | * | keccak256(abi.encode("DECREASE_ORDER_GAS_LIMIT"));
81 | |
82 | | bytes32 public constant SWAP_ORDER_GAS_LIMIT =
83 | * | keccak256(abi.encode("SWAP_ORDER_GAS_LIMIT"));
84 | |
85 | | bytes32 public constant SINGLE_SWAP_GAS_LIMIT =
86 | * | keccak256(abi.encode("SINGLE_SWAP_GAS_LIMIT"));
87 | |
88 | | bytes32 public constant POSITION_FEE_FACTOR =
89 | * | keccak256(abi.encode("POSITION_FEE_FACTOR"));
90 | |
91 | | bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED =
92 | * | keccak256(abi.encode("EXECUTE_ORDER_FEATURE_DISABLED"));
93 | |
94 | | bytes32 public constant IS_LONG = keccak256(abi.encode("IS_LONG"));
95 | |
96 | * | bytes32 public constant referralCode = bytes32(0);
97 | |
98 | * | uint256 public constant PRECISION = 1e30;
99 | |
100 | | uint256 public constant BASIS_POINTS_DIVISOR = 10_000;
101 | |
102 | | address public orderHandler;
103 | | IExchangeRouter public gExchangeRouter;
104 | | address router;
105 | | IDataStore public dataStore;
106 | | address public orderVault;
107 | | IReader public reader;
108 | | address public referralStorage;
109 | |
110 | | address public perpVault;
111 | | uint256 public slippage; // GMX swap slippage
112 | | uint256 public priceOffset; // GMX position execution price offset to allow some price impact
113 | |
114 | * | OrderQueue public queue;
115 | |
116 | | event ClaimFundingFees(address token, uint256 amount);
117 | | event ClaimFundingFeeExecutionError(address[], address[], address);
118 | |
119 | | modifier validCallback(bytes32 key, Order.Props memory order) {
120 | * | require(msg.sender == address(orderHandler), "invalid caller");
121 | |
122 | * | require(order.addresses.account == address(this), "not mine");
123 | |
124 | * | if (order.numbers.orderType != Order.OrderType.Liquidation) {
125 | * | require(queue.requestKey == key, "invalid request key");
126 | | }
127 | |
128 | | _;
129 | | }
130 | |
131 | | function initialize(
132 | | address _orderHandler,
133 | | address _gExchangeRouter,
134 | | address _dataStore,
135 | | address _orderVault,
136 | | address _reader,
137 | | address _referralStorage,
138 | | address _router
139 | | ) external initializer {
140 | | __Ownable2Step_init();
141 | | slippage = 30;
142 | | priceOffset = 30;
143 | |
144 | | orderHandler = _orderHandler;
145 | | gExchangeRouter = IExchangeRouter(_gExchangeRouter);
146 | | dataStore = IDataStore(_dataStore);
147 | | orderVault = _orderVault;
148 | | reader = IReader(_reader);
149 | | referralStorage = _referralStorage;
150 | | router = _router;
151 | | }
152 | |
153 | | receive() external payable {}
154 | |
155 | | /**
156 | | * @notice Retrieves the position information for a given key and market prices.
157 | | * @param key The key representing the position.
158 | | * @param prices The current market prices for the relevant tokens.
159 | | * @return PositionData The data structure containing detailed information about the position.
160 | | */
161 | * | function getPositionInfo(
162 | | bytes32 key,
163 | | MarketPrices memory prices
164 | * | ) external view returns (PositionData memory) {
165 | * | if (key == bytes32(0)) {
166 | * | return
167 | * | PositionData({
168 | * | sizeInUsd: 0,
169 | * | sizeInTokens: 0,
170 | * | collateralAmount: 0,
171 | * | netValue: 0,
172 | * | isLong: true
173 | | });
174 | | }
175 | * | PositionInfo memory positionInfo = reader.getPositionInfo(
176 | * | address(dataStore),
177 | * | referralStorage,
178 | * | key,
179 | * | prices,
180 | * | uint256(0),
181 | * | address(0),
182 | * | true
183 | | );
184 | * | uint256 netValue;
185 | * | if (positionInfo.basePnlUsd >= 0) {
186 | * | netValue =
187 | * | positionInfo.position.numbers.collateralAmount *
188 | * | prices.shortTokenPrice.min +
189 | * | uint256(positionInfo.basePnlUsd) -
190 | * | positionInfo.fees.borrowing.borrowingFeeUsd -
191 | * | positionInfo.fees.funding.fundingFeeAmount *
192 | * | prices.shortTokenPrice.min -
193 | * | positionInfo.fees.positionFeeAmount *
194 | * | prices.shortTokenPrice.min;
195 | | } else {
196 | * | netValue =
197 | * | positionInfo.position.numbers.collateralAmount *
198 | * | prices.shortTokenPrice.min -
199 | * | (uint256(-positionInfo.basePnlUsd) +
200 | * | positionInfo.fees.borrowing.borrowingFeeUsd) -
201 | * | positionInfo.fees.funding.fundingFeeAmount *
202 | * | prices.shortTokenPrice.min -
203 | * | positionInfo.fees.positionFeeAmount *
204 | * | prices.shortTokenPrice.min;
205 | | }
206 | |
207 | * | return
208 | * | PositionData({
209 | * | sizeInUsd: positionInfo.position.numbers.sizeInUsd,
210 | * | sizeInTokens: positionInfo.position.numbers.sizeInTokens,
211 | * | collateralAmount: positionInfo
212 | | .position
213 | | .numbers
214 | | .collateralAmount,
215 | * | netValue: netValue,
216 | * | isLong: positionInfo.position.flags.isLong
217 | | });
218 | | }
219 | |
220 | * | function willPositionCollateralBeSufficient(
221 | | MarketPrices memory prices,
222 | | bytes32 positionKey,
223 | | address market,
224 | | bool isLong,
225 | | uint256 sizeDeltaUsd
226 | * | ) external view returns (bool) {
227 | * | PositionInfo memory positionInfo = reader.getPositionInfo(
228 | * | address(dataStore),
229 | * | referralStorage,
230 | * | positionKey,
231 | * | prices,
232 | * | uint256(0),
233 | * | address(0),
234 | * | true
235 | | );
236 | * | int256 realizedPnlUsd;
237 | * | if (positionInfo.basePnlUsd > 0) {
238 | | realizedPnlUsd = ((uint256(positionInfo.basePnlUsd) *
239 | | sizeDeltaUsd) / positionInfo.position.numbers.sizeInUsd)
240 | | .toInt256();
241 | | } else {
242 | * | realizedPnlUsd = -((uint256(-positionInfo.basePnlUsd) *
243 | * | uint256(sizeDeltaUsd)) /
244 | * | uint256(positionInfo.position.numbers.sizeInUsd)).toInt256();
245 | | }
246 | * | MarketUtils.WillPositionCollateralBeSufficientValues
247 | * | memory values = MarketUtils
248 | | .WillPositionCollateralBeSufficientValues({
249 | * | positionSizeInUsd: positionInfo.position.numbers.sizeInUsd,
250 | * | positionCollateralAmount: positionInfo
251 | | .position
252 | | .numbers
253 | | .collateralAmount,
254 | * | realizedPnlUsd: realizedPnlUsd,
255 | * | openInterestDelta: -int256(sizeDeltaUsd)
256 | | });
257 | * | MarketProps memory marketInfo = getMarket(market);
258 | * | (bool willBeSufficient, ) = MarketUtils
259 | | .willPositionCollateralBeSufficient(
260 | * | dataStore,
261 | * | marketInfo,
262 | * | prices,
263 | * | isLong,
264 | * | values
265 | | );
266 | |
267 | * | return willBeSufficient;
268 | | }
269 | |
270 | * | function getPnl(
271 | | bytes32 key,
272 | | MarketPrices memory prices,
273 | | uint256 sizeDeltaUsd
274 | * | ) external view returns (int256) {
275 | * | if (key == bytes32(0)) {
276 | * | return 0;
277 | | }
278 | * | PositionInfo memory positionInfo = reader.getPositionInfo(
279 | * | address(dataStore),
280 | * | referralStorage,
281 | * | key,
282 | * | prices,
283 | * | sizeDeltaUsd,
284 | * | address(0),
285 | * | true
286 | | );
287 | |
288 | * | return positionInfo.pnlAfterPriceImpactUsd;
289 | | }
290 | |
291 | | /**
292 | | * @notice Retrieves the position size in USD for a given key.
293 | | * @param key The key representing the position.
294 | | * @return sizeInUsd The size of the position in USD.
295 | | */
296 | * | function getPositionSizeInUsd(
297 | | bytes32 key
298 | * | ) external view returns (uint256 sizeInUsd) {
299 | * | sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD)));
300 | | }
301 | |
302 | | /**
303 | | * @notice Retrieves the market properties for a given market address.
304 | | * @param market The address of the market to retrieve properties for.
305 | | * @return MarketProps The data structure containing properties of the specified market.
306 | | */
307 | * | function getMarket(
308 | | address market
309 | * | ) public view returns (MarketProps memory) {
310 | * | return reader.getMarket(address(dataStore), market);
311 | | }
312 | |
313 | | /**
314 | | * @notice Calculates the position fee in USD for a given market and size delta.
315 | | * @param market The address of the market.
316 | | * @param sizeDeltaUsd The USD value of the size delta.
317 | | * @param forPositiveImpact Indicates if the order action balances open interest (true) or not (false).
318 | | * @return positionFeeAmount The calculated position fee amount in USD.
319 | | */
320 | * | function getPositionFeeUsd(
321 | | address market,
322 | | uint256 sizeDeltaUsd,
323 | | bool forPositiveImpact
324 | * | ) external view returns (uint256 positionFeeAmount) {
325 | * | uint256 positionFeeFactor = dataStore.getUint(
326 | * | keccak256(
327 | * | abi.encode(POSITION_FEE_FACTOR, market, forPositiveImpact)
328 | | )
329 | | );
330 | * | positionFeeAmount = (sizeDeltaUsd * positionFeeFactor) / PRECISION;
331 | | }
332 | |
333 | | /**
334 | | * @notice Retrieves the current market prices for a given market.
335 | | * @param market The address of the market to retrieve prices for.
336 | | * @return MarketPrices The data structure containing the current prices for the market's index, long, and short tokens.
337 | | */
338 | * | function getMarketPrices(
339 | | address market
340 | * | ) external view returns (MarketPrices memory) {
341 | * | MarketPrices memory prices;
342 | * | MarketProps memory marketInfo = reader.getMarket(
343 | * | address(dataStore),
344 | * | market
345 | | );
346 | * | address oracle = IOrderHandler(orderHandler).oracle();
347 | * | prices.indexTokenPrice = IOracle(oracle).getPrimaryPrice(
348 | * | marketInfo.indexToken
349 | | );
350 | * | prices.longTokenPrice = IOracle(oracle).getPrimaryPrice(
351 | * | marketInfo.longToken
352 | | );
353 | * | prices.shortTokenPrice = IOracle(oracle).getPrimaryPrice(
354 | * | marketInfo.shortToken
355 | | );
356 | * | return prices;
357 | | }
358 | |
359 | | /**
360 | | * @notice Calculates the execution gas limit for a given order type and callback gas limit.
361 | | * @param orderType The type of order (e.g., MarketIncrease, MarketDecrease, etc.).
362 | | * @param _callbackGasLimit The gas limit specified for the callback.
363 | | * @return executionGasLimit The calculated execution gas limit.
364 | | */
365 | * | function getExecutionGasLimit(
366 | | Order.OrderType orderType,
367 | | uint256 _callbackGasLimit
368 | * | ) public view returns (uint256 executionGasLimit) {
369 | * | uint256 baseGasLimit = dataStore.getUint(
370 | | ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1
371 | | );
372 | * | uint256 oraclePriceCount = 5; // maximum number of oralce prices
373 | * | baseGasLimit +=
374 | * | dataStore.getUint(ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) *
375 | * | oraclePriceCount;
376 | * | uint256 multiplierFactor = dataStore.getUint(
377 | | ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR
378 | | );
379 | * | uint256 gasPerSwap = dataStore.getUint(SINGLE_SWAP_GAS_LIMIT);
380 | * | uint256 estimatedGasLimit;
381 | * | if (orderType == Order.OrderType.MarketIncrease) {
382 | * | estimatedGasLimit =
383 | * | dataStore.getUint(INCREASE_ORDER_GAS_LIMIT) +
384 | * | gasPerSwap;
385 | * | } else if (orderType == Order.OrderType.MarketDecrease) {
386 | * | estimatedGasLimit =
387 | * | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) +
388 | * | gasPerSwap;
389 | * | } else if (orderType == Order.OrderType.LimitDecrease) {
390 | | estimatedGasLimit =
391 | | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) +
392 | | gasPerSwap;
393 | * | } else if (orderType == Order.OrderType.StopLossDecrease) {
394 | | estimatedGasLimit =
395 | | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) +
396 | | gasPerSwap;
397 | * | } else if (orderType == Order.OrderType.MarketSwap) {
398 | * | estimatedGasLimit =
399 | * | dataStore.getUint(SWAP_ORDER_GAS_LIMIT) +
400 | * | gasPerSwap;
401 | | }
402 | | // multiply 1.2 (add some buffer) to ensure that the creation transaction does not revert.
403 | * | executionGasLimit =
404 | * | baseGasLimit +
405 | * | ((estimatedGasLimit + _callbackGasLimit) * multiplierFactor) /
406 | | PRECISION;
407 | | }
408 | |
409 | | /**
410 | | * @notice Callback function called by the GMX order execution controller.
411 | | * @dev This function is invoked after the GMX keeper executes the requested order within the next few blocks.
412 | | * @param requestKey The key of the executed order.
413 | | * @param order The data of the executed order.
414 | | * @param eventData The event data associated with the order execution.
415 | | */
416 | * | function afterOrderExecution(
417 | | bytes32 requestKey,
418 | | Order.Props memory order,
419 | | EventLogData memory eventData
420 | * | ) external override validCallback(requestKey, order) {
421 | * | uint256 claimed;
422 | |
423 | | // Claim funding fees for non-swap orders
424 | * | if (order.numbers.orderType != Order.OrderType.MarketSwap) {
425 | * | address[] memory markets = new address[](2);
426 | * | address[] memory tokens = new address[](2);
427 | * | markets[0] = order.addresses.market;
428 | * | markets[1] = order.addresses.market;
429 | * | MarketProps memory marketInfo = reader.getMarket(
430 | * | address(dataStore),
431 | * | order.addresses.market
432 | | );
433 | * | tokens[0] = marketInfo.indexToken;
434 | * | tokens[1] = marketInfo.shortToken;
435 | * | try
436 | * | gExchangeRouter.claimFundingFees(markets, tokens, perpVault)
437 | * | returns (uint256[] memory claimedAmounts) {
438 | * | claimed = claimedAmounts[0];
439 | * | emit ClaimFundingFees(tokens[0], claimed);
440 | | } catch {
441 | * | emit ClaimFundingFeeExecutionError(markets, tokens, perpVault);
442 | | }
443 | | }
444 | * | bytes32 positionKey = keccak256(
445 | * | abi.encode(
446 | * | address(this),
447 | * | order.addresses.market,
448 | * | order.addresses.initialCollateralToken,
449 | * | order.flags.isLong
450 | | )
451 | | );
452 | |
453 | | // Determine output token and amount for swap or decrease orders
454 | * | address outputToken;
455 | * | uint256 outputAmount;
456 | * | if (
457 | * | order.numbers.orderType == Order.OrderType.MarketSwap ||
458 | * | order.numbers.orderType == Order.OrderType.MarketDecrease
459 | | ) {
460 | * | outputToken = eventData.addressItems.items[0].value;
461 | * | outputAmount = eventData.uintItems.items[0].value;
462 | | }
463 | | // Construct order result data and notify perpetual vault
464 | * | IGmxUtils.OrderResultData memory orderResultData = IGmxUtils
465 | | .OrderResultData(
466 | * | order.numbers.orderType,
467 | * | order.flags.isLong,
468 | * | order.numbers.sizeDeltaUsd,
469 | * | outputToken,
470 | * | outputAmount,
471 | * | queue.isSettle
472 | | );
473 | * | IPerpetualVault(perpVault).afterOrderExecution(
474 | * | requestKey,
475 | * | positionKey,
476 | * | orderResultData
477 | | );
478 | * | delete queue;
479 | | }
480 | |
481 | | /**
482 | | * @notice Callback function called by the GMX order execution controller.
483 | | * @dev This function is called when the submitted order data is incorrect or when a user cancels their order.
484 | | * @param key The request key of the canceled order.
485 | | * @param order The data of the canceled order.
486 | | */
487 | * | function afterOrderCancellation(
488 | | bytes32 key,
489 | | Order.Props memory order,
490 | | EventLogData memory /* eventData */
491 | * | ) external override validCallback(key, order) {
492 | * | IGmxUtils.OrderResultData memory orderResultData = IGmxUtils
493 | | .OrderResultData(
494 | * | order.numbers.orderType,
495 | * | order.flags.isLong,
496 | * | order.numbers.sizeDeltaUsd,
497 | * | address(0),
498 | * | 0,
499 | * | queue.isSettle
500 | | );
501 | * | IPerpetualVault(perpVault).afterOrderCancellation(
502 | * | key,
503 | * | order.numbers.orderType,
504 | * | orderResultData
505 | | );
506 | * | delete queue;
507 | | }
508 | |
509 | | /**
510 | | * limit order can be set with greater size than the available amount in the pool
511 | | * so when it reaches to the trigger price, it cannot be executed and be frozen.
512 | | * and at that time, `afterOrderFrozen` is called as a callback function.
513 | | * According to the above rule, `afterOrderFrozen` is never called in our contract logic
514 | | */
515 | | function afterOrderFrozen(
516 | | bytes32 key,
517 | | Order.Props memory order,
518 | | EventLogData memory
519 | | ) external override validCallback(key, order) {}
520 | |
521 | | /**
522 | | * Callback function from GMX to refund remaining gas.
523 | | * @param key request key
524 | | */
525 | | function refundExecutionFee(
526 | | bytes32 key,
527 | | EventLogData memory
528 | | ) external payable {}
529 | |
530 | | /**
531 | | * @notice
532 | | * Returns the remaining execution fee after flow is completed.
533 | | * @param receipient address to receive the remaining fee
534 | | * @param amount amount of the remaining fee
535 | | */
536 | | function refundExecutionFee(address receipient, uint256 amount) external {
537 | | require(msg.sender == perpVault, "invalid caller");
538 | | payable(receipient).transfer(amount);
539 | | }
540 | |
541 | | /**
542 | | * @notice Sets the address of the perpetual vault.
543 | | * @dev This function can only be called once. It requires the perpetual vault address to be non-zero and not already set.
544 | | * @param _perpVault The address of the perpetual vault.
545 | | */
546 | | function setPerpVault(address _perpVault) external {
547 | | require(_perpVault != address(0), "zero address");
548 | | require(perpVault == address(0), "already set");
549 | | perpVault = _perpVault;
550 | | }
551 | |
552 | | // /**
553 | | // * @notice Creates an order with additional callback data.
554 | | // * @dev This function stores the provided callback data and then calls the core `createOrder` function.
555 | | // * @param orderType The type of the order (e.g., MarketIncrease, MarketDecrease, etc.).
556 | | // * @param orderData The data associated with the order.
557 | | // * @param prices The market prices used for order creation.
558 | | // * @param callbackdata Additional callback data to be used during order execution.
559 | | // * @return The request key of the created order.
560 | | // */
561 | | // function createOrder(
562 | | // Order.OrderType orderType,
563 | | // IGmxUtils.OrderData memory orderData,
564 | | // MarketPrices memory prices,
565 | | // bytes memory callbackdata
566 | | // ) external returns (bytes32) {
567 | | // queue.callbackdata = callbackdata;
568 | | // return createOrder(orderType, orderData, prices);
569 | | // }
570 | |
571 | | /**
572 | | * @notice Creates an order.
573 | | * @dev This function requires the receipient to be the perpetual vault and ensures sufficient ETH balance for the execution fee.
574 | | * It handles token approvals, transfers, and constructs the order parameters before creating the order via `gExchangeRouter`.
575 | | * @param orderType The type of the order (e.g., MarketIncrease, MarketDecrease, etc.).
576 | | * @param orderData The data associated with the order.
577 | | * @return The request key of the created order.
578 | | */
579 | * | function createOrder(
580 | | Order.OrderType orderType,
581 | | IGmxUtils.OrderData memory orderData
582 | * | ) public returns (bytes32) {
583 | * | require(msg.sender == perpVault, "invalid caller");
584 | * | uint256 positionExecutionFee = getExecutionGasLimit(
585 | * | orderType,
586 | * | orderData.callbackGasLimit
587 | * | ) * tx.gasprice;
588 | * | require(
589 | * | address(this).balance >= positionExecutionFee,
590 | | "insufficient eth balance"
591 | | );
592 | |
593 | | // check if execution feature is enabled
594 | * | bytes32 executeOrderFeatureKey = keccak256(
595 | * | abi.encode(EXECUTE_ORDER_FEATURE_DISABLED, orderHandler, orderType)
596 | | );
597 | * | require(
598 | * | dataStore.getBool(executeOrderFeatureKey) == false,
599 | | "gmx execution disabled"
600 | | );
601 | |
602 | * | gExchangeRouter.sendWnt{value: positionExecutionFee}(
603 | * | orderVault,
604 | * | positionExecutionFee
605 | | );
606 | * | if (
607 | * | orderType == Order.OrderType.MarketSwap ||
608 | * | orderType == Order.OrderType.MarketIncrease
609 | | ) {
610 | * | IERC20(orderData.initialCollateralToken).safeApprove(
611 | * | address(router),
612 | * | orderData.amountIn
613 | | );
614 | * | gExchangeRouter.sendTokens(
615 | * | orderData.initialCollateralToken,
616 | * | orderVault,
617 | * | orderData.amountIn
618 | | );
619 | * | queue.tokenIn = orderData.initialCollateralToken;
620 | * | queue.amountIn = orderData.amountIn;
621 | | }
622 | * | CreateOrderParamsAddresses
623 | * | memory paramsAddresses = CreateOrderParamsAddresses({
624 | * | receiver: perpVault,
625 | * | cancellationReceiver: address(perpVault),
626 | * | callbackContract: address(this),
627 | * | uiFeeReceiver: address(0),
628 | * | market: orderData.market,
629 | * | initialCollateralToken: orderData.initialCollateralToken,
630 | * | swapPath: orderData.swapPath
631 | | });
632 | |
633 | * | CreateOrderParamsNumbers
634 | * | memory paramsNumber = CreateOrderParamsNumbers({
635 | * | sizeDeltaUsd: orderData.sizeDeltaUsd,
636 | * | initialCollateralDeltaAmount: orderData
637 | | .initialCollateralDeltaAmount,
638 | * | triggerPrice: 0,
639 | * | acceptablePrice: orderData.acceptablePrice,
640 | * | executionFee: positionExecutionFee,
641 | * | callbackGasLimit: orderData.callbackGasLimit,
642 | * | minOutputAmount: orderData.minOutputAmount // this param is used when swapping. is not used in opening position even though swap involved.
643 | | });
644 | * | CreateOrderParams memory params = CreateOrderParams({
645 | * | addresses: paramsAddresses,
646 | * | numbers: paramsNumber,
647 | * | orderType: orderType,
648 | * | decreasePositionSwapType: Order
649 | | .DecreasePositionSwapType
650 | | .SwapPnlTokenToCollateralToken,
651 | * | isLong: orderData.isLong,
652 | * | shouldUnwrapNativeToken: false,
653 | * | autoCancel: false,
654 | | referralCode: referralCode
655 | | });
656 | |
657 | * | (bool success, bytes32 requestKey) = gExchangeRouter.createOrderFUZZ(
658 | * | params
659 | | );
660 | |
661 | * | require(success, "Order creation failed on GMX exchange router");
662 | * | queue.requestKey = requestKey;
663 | * | return requestKey;
664 | | }
665 | |
666 | | /**
667 | | * @notice Settles an order by creating a MarketDecrease order with minimal collateral delta amount.
668 | | * @dev This function calculates the execution fee, ensures sufficient ETH balance, sets up the order parameters,
669 | | * and creates the order via the `gExchangeRouter`.
670 | | * @param orderData The data associated with the order, encapsulated in an `OrderData` struct.
671 | | * @return The request key of the created order.
672 | | */
673 | * | function settle(
674 | | IGmxUtils.OrderData memory orderData
675 | * | ) external returns (bytes32) {
676 | * | require(msg.sender == perpVault, "invalid caller");
677 | * | uint256 positionExecutionFee = getExecutionGasLimit(
678 | * | Order.OrderType.MarketDecrease,
679 | * | orderData.callbackGasLimit
680 | * | ) * tx.gasprice;
681 | * | require(
682 | * | address(this).balance >= positionExecutionFee,
683 | | "insufficient eth balance"
684 | | );
685 | * | gExchangeRouter.sendWnt{value: positionExecutionFee}(
686 | * | orderVault,
687 | * | positionExecutionFee
688 | | );
689 | * | CreateOrderParamsAddresses
690 | * | memory paramsAddresses = CreateOrderParamsAddresses({
691 | * | receiver: perpVault,
692 | * | cancellationReceiver: address(perpVault),
693 | * | callbackContract: address(this),
694 | * | uiFeeReceiver: address(0),
695 | * | market: orderData.market,
696 | * | initialCollateralToken: orderData.initialCollateralToken,
697 | * | swapPath: new address[](0)
698 | | });
699 | * | CreateOrderParamsNumbers
700 | * | memory paramsNumber = CreateOrderParamsNumbers({
701 | * | sizeDeltaUsd: 0,
702 | * | initialCollateralDeltaAmount: 1,
703 | * | triggerPrice: 0,
704 | * | acceptablePrice: 0,
705 | * | executionFee: positionExecutionFee,
706 | * | callbackGasLimit: orderData.callbackGasLimit,
707 | * | minOutputAmount: 0 // this param is used when swapping. is not used in opening position even though swap involved.
708 | | });
709 | * | CreateOrderParams memory params = CreateOrderParams({
710 | * | addresses: paramsAddresses,
711 | * | numbers: paramsNumber,
712 | * | orderType: Order.OrderType.MarketDecrease,
713 | * | decreasePositionSwapType: Order
714 | | .DecreasePositionSwapType
715 | | .SwapPnlTokenToCollateralToken,
716 | * | isLong: orderData.isLong,
717 | * | shouldUnwrapNativeToken: false,
718 | * | autoCancel: false,
719 | | referralCode: referralCode
720 | | });
721 | * | bytes32 requestKey = gExchangeRouter.createOrder(params);
722 | * | queue.requestKey = requestKey;
723 | * | queue.isSettle = true;
724 | * | return requestKey;
725 | | }
726 | |
727 | | /**
728 | | * @notice
729 | | * GMX keepers would not always execute orders in a reasonable amount of time.
730 | | * This function is called when the requested Order is not executed in GMX side.
731 | | */
732 | | function cancelOrder() external {
733 | | require(msg.sender == perpVault, "invalid caller");
734 | | require(queue.requestKey != bytes32(0), "zero value");
735 | | gExchangeRouter.cancelOrder(queue.requestKey);
736 | | }
737 | |
738 | | function claimCollateralRebates(
739 | | address[] memory markets,
740 | | address[] memory tokens,
741 | | uint256[] memory timeKeys,
742 | | address receiver
743 | | ) external {
744 | | require(msg.sender == perpVault, "invalid caller");
745 | | gExchangeRouter.claimCollateral(markets, tokens, timeKeys, receiver);
746 | | }
747 | |
748 | | function setSlippage(uint256 _slippage) external onlyOwner {
749 | | slippage = _slippage;
750 | | }
751 | |
752 | | function setPriceOffset(uint256 _priceOffset) external onlyOwner {
753 | | priceOffset = _priceOffset;
754 | | }
755 | |
756 | | /**
757 | | * @notice Withdraws all ETH from the contract to the owner's address.
758 | | * @dev This function can only be called by the owner of the contract.
759 | | * @return The balance of ETH withdrawn from the contract.
760 | | */
761 | | function withdrawEth() external onlyOwner returns (uint256) {
762 | | uint256 balance = address(this).balance;
763 | | payable(msg.sender).transfer(balance);
764 | | return balance;
765 | | }
766 | | }
767 | |